AJax
1. 前端视图
ajax\src\main\webapp\ajax-register.html
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<form class="form-horizontal" role="form">
<div>
<tr>
<td>账号</td>
<td class="inputs">
<input name="username" type="text" id="username">
</td>
<br>
<span id="username_err" class="err_msg" style="display:none">用户名已存在</span>
</tr>
</div>
<div>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="text" id="password">
</td>
</tr>
</div>
</form>
<script>
// 1.给用户输入框绑定失去焦点事件
document.getElementById("username").onblur = function () {
// alert("TTT");
// 2.发送ajax请求
// 获取参数
var username = this.value;
// 2.1.创建核心对象
const xhttp = new XMLHttpRequest();
// 2.2.发送请求
// 通过selectUserservlet向servlet.java发送usernema数据
xhttp.open("GET", "http://localhost:8080/ajax/selectUserservlet?username=" + username);
// 传两个参数:
// xhttp.open("GET", "http://localhost:8080/ajax/selectUserservlet?username=test2&username2=test2");
xhttp.send();
// 2.3.获取响应
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
//判断
if (this.responseText == "true") {
// 用户名已存在
// 将展示(display)启用,显示提示信息
document.getElementById("username_err").style.display = '';
}
else {
// 用户名不存在
// 将展示(display)关闭,清除提示信息
document.getElementById("username_err").style.display = 'none';
}
}
};
}
</script>
</body>
</html>
2. 后端
ajax\src\main\java\com\mercurows\web\servlet\servlet.java
package com.mercurows.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/selectUserservlet")
public class servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.接受用户名
String username = req.getParameter("username");
System.out.println(username);
// 2.调用service查询user对象
boolean flag = true;
// 3.标记响应
resp.getWriter().write("" + flag);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
3. 请求链接如何确定?
xhttp.open("GET", "http://localhost:8080/ajax/selectUserservlet");
上述不带参数传递的请求连接为:http://localhost:8080/ajax/selectUserservlet
具体步骤:
用tomcat打开项目
一开始默认进来是这样的:
又因为要跳转到后端的servlet的servlet.java
页面,通过上面的注解 **@WebServlet(“/selectUserservlet”)**知道请求链接后面应该跟随selectUserservlet
若想传递参数则需要修改链接为:
http://localhost:8080/ajax/selectUserservlet?username=" + username
此时后端接受参数方法为:
String username = req.getParameter("username");
4. 项目结构
Axios
0. 导入js文件
去网上找到axios.js
并导入项目中
然后在前端中导入
<script src="js/axios.js"></script>
1. 前端视图
ajax\src\main\webapp\axios-demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="js/axios.js"></script>
<!-- 1.get方式 -->
<!-- <script>
axios({
method:"get",
url:"http://localhost:8080/ajax/axiosServlet?username=zhangsan"
}).then(function (resp){
alert(JSON.stringify(resp.data));
})
</script> -->
<!-- 2.post方式 -->
<script>
axios({
method:"post",
url:"http://localhost:8080/ajax/axiosServlet",
data:"username=zhangsan"
}).then(function (resp){
alert(JSON.stringify(resp.data));
})
</script>
</body>
</html>
2. 后端
ajax\src\main\java\com\mercurows\web\servlet\AxiosServlet.java
package com.mercurows.web.servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
@WebServlet("/axiosServlet")
public class AxiosServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
System.out.println("get..");
// 1.接受用户名
String username = req.getParameter("username");
// 2.响应数据
// res.getWriter().write("hello axios");
System.out.println(username);
Map<Object,Object> data1 = new HashMap<>();
data1.put("name", "Alice");
data1.put("age", 12);
data1.put("measurements", new int[] { 60, 70, 70 });
JSONObject object = JSONObject.fromObject(data1); //创建Json对象
//将json对象转化为字符串在终端输出
System.out.print(object.toString());
//把json数据返回给浏览器:
res.getWriter().write(object.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException {
System.out.println("pos..");
this.doGet(req,res);
}
}
3. 确定请求链接
参考AJax中的方法
**注意:**上面后端中使用JSONObject
了传递JSON数据,可参考博客:简单的后端传送json格式至前端正确处理方法
4. 项目结构
Servlet优化
情景想象:对于Student实体对象有添加(add)、查找(select)等方法,按照我旧的设计方法,会设计两个servlet类:AddStudentServlet、SelectALLStudentServlet。如果后面后续又出现了更多操作,这使得servlet类的管理出现不便。这时我可以采取与MyBatis类似的处理方法进行映射,见:MyBatis简单入门。Student专门写个成一个StudentServlet类,然后原本的AddStudentServlet、SelectALLStudentServlet写成里面的成员方法。
1.自定义servlet类重写service方法
自定义继承了HttpServlet
类的子类,并且重写protected void service(HttpServletRequest req, HttpServletResponse resp)
方法–根据请求链接来决定是调用doGet
还是doPost
之类的,源码可以见:源码,重写了该方法之后也就可以做到无需写doGet
、doPost
等方法。
ajax\src\main\java\com\mercurows\web\servlet\BaseServlet.java
package com.mercurows.web.servlet;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// @WebServlet("/selectUserservlet")
// 替换HttpServlet,根据请求的最后一段路径来进行分发
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.1获取请求路径,即浏览器输入栏的链接
String uri = req.getRequestURI();
// System.out.println(uri);
// 1.2获取最后一段路径,即StudentServlet中的成员方法名
//这里的方法名即指
int index = uri.lastIndexOf('/');
String methodName = uri.substring(index + 1);
// System.out.println(methodName);
// 2.执行方法
// 2.1 获取TeacherServlet、StudentServlet字节码对象Class
// 谁调用该方法,该方法中的this就是谁
Class<? extends Object> cls = this.getClass();
cls.getMethods();
// 2.2获取方法Method对象
try {
// 方法名称、方法参数对应的class
Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
// 2.3参数:调用方法的类,该方法对应的参数
method.invoke(this, req, resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
2. 映射servlet的类
与以往编写servlet
类要继承HttpServlet
类一样,这里因为BaseServlet
继承了HttpServlet
,所以直接继承BaseServlet
即可,如:
ajax\src\main\java\com\mercurows\web\servlet\StudentServlet.java
package com.mercurows.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/student/*")
public class StudentServlet extends BaseServlet {
public void selectAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Student selectAll..");
}
public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Student add..");
}
public void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Student del..");
}
}
这里的@WebServlet("/student/*")
表示通配符,表示当要执行StudentServlet
中任一方法时(如selectAll方法,则路径应该是:/student/selectAll
)便会见控制权转交给对应方法。
3. 具体执行流程
运行tomcat打开项目浏览器:
假如要执行StudentServlet
中的成员方法,则具体路径为:http://localhost:8080/ajax/student/selectAll
**具体的:**当我在浏览器中输入http://localhost:8080/ajax/student/del时,执行流程如下
- 请求由服务器接收,并传递给与路径匹配的Servlet,即
BaseServlet
。BaseServlet
的service
方法被调用,传入HttpServletRequest
和HttpServletResponse
对象。- 在
service
方法内部,通过req.getRequestURI()
获取请求的URI,即/ajax/student/del
。- 然后,通过
uri.lastIndexOf('/')
获取最后一个斜杠的索引,这里是14
。- 使用
uri.substring(index)
截取最后一段路径,即/del
,并将其存储在methodName
变量中。methodName
现在包含要执行的方法名。BaseServlet
的service
方法执行完毕,控制权传递回StudentServlet
。StudentServlet
继承自BaseServlet
,因此它会继承service
方法。service
方法在StudentServlet
中未被重写,因此将调用BaseServlet
中的service
方法。BaseServlet
的service
方法将执行上述步骤来解析URI,并确定要执行的方法名为/del
。service
方法输出/ajax/student/del
和/del
的日志信息。service
方法执行完毕,请求处理完成。总结:请求首先由
BaseServlet
接收并解析URI,然后确定要执行的方法名为/del
。然后控制权传递给StudentServlet
,但由于StudentServlet
没有重写service
方法,因此将继续执行BaseServlet
中的service
方法。
4. 多个映射servlet的类
假如,现在又多了TeacherServlet.java
,同理也只需要继承BaseServlet.java
即可,而且BaseServlet.java
不需要做出任何修改。
ajax\src\main\java\com\mercurows\web\servlet\TeacherServlet.java
package com.mercurows.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/teacher/*")
public class TeacherServlet extends BaseServlet {
public void selectAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("teacher selectAll..");
}
public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("teacher add..");
}
}