Ajax&Axios&JSON
# Ajax
# Ajax 概述
AJAX(Asynchronous JavaScript And XML):异步的JavaScript和XML。
AJAX中的JavaScript表名该技术和前端有关,XML是指以此进行数据交换。JavaScript和XML这两种技术我们前面都学习过。
# Ajax 作用
AJAX作用有以下两方面:
- 与服务器进行数据交换:通过AJAX可以给服务器发送请求,服务器将数据直接响应给浏览器。下面先来看之前功能处理浏览器请求的流程图:
如上图,Servlet
调用完业务逻辑层后将数据存储到域对象中,然后跳转到指定的JSP页面,在页面上使用EL 表达式和JSTL标签进行数据的展示。
但当我们学习AJAX后,就可以使用AJAX 和服务器进行通信,以达到使用HTML+AJAX来替换JSP页面。如下图,浏览器发送请求到servlet
,servlet
调用完业务逻辑层后将数据直接响应回给浏览器页面,页面使用HTML进行数据展示。
- 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容的技术,如:搜索查询、注册时用户名是否可用校验等等...
如上图所示的效果我们经常会见到,在我们输入一些关键字(如:奥运)后就会在下面联想出相关的内容,那么联想出来的这部分数据肯定是存储在百度的服务器上,但是我们并没有看到页面重新刷新,这就是更新局部页面的效果。再比如下图:
在用户名的输入框输入用户名,当输入框失去焦点时,如果用户名已经被占用就会在下方展示提示的信息,在这整个过程中也没有页面的刷新,知识在局部展示了提示信息,这同样也是更新局部页面的效果。
# 同步和异步
了解了局部刷新后,下面我们再来学习下同步和异步:
- 同步发送请求过程如下:
浏览器页面在发送请求给服务器,在服务器处理请求的过程中,浏览器页面不能做其他的操作,只能等到服务器响应结束后才能继续其他的操作。
- 异步发送请求过程如下
浏览器页面发送请求给服务器,在服务器处理请求的过程中,浏览器页面还可以做其他的操作。
# Ajax 快速入门
# 服务端实现
在项目的com.itheima
创建一个ajax
包,并在该包下创建一个AjaxServlet
:
package com.itheima.ajax;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 响应数据
response.getWriter().write("hello ajax~");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 客户端实现
在webapp
目录下创建一个新的目录ajax
,并在该目录下创建AjaxDemo1.html
页面,在该页面中书写如下的ajax
代码
- 创建核心对象,不同的浏览器创建对象的方式是不同的,需要考虑浏览器的兼容性
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
2
3
4
5
6
7
- 发送请求
// 建立连接
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// 通过this.responseText可以获取到服务端响应的数据
alert(this.responseText);
}
};
2
3
4
5
6
7
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
// 1. 创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2. 发送请求
xhttp.open("GET", "http://localhost/course/ajaxServlet");
xhttp.send();
// 3. 获取响应数据
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
alert(this.responseText);
}
};
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 测试
在浏览器地址栏输入http://localhost/course/ajax/AjaxDemo1.html,在页面加载的时候就会发送ajax
请求,效果如下:
我们可以通过开发者模式查看发送的AJAX请求,在浏览器上按F12快捷键
上图是查看所有的请求,如果只想看异步请求的话,点击All旁边的XHR,会发现只展示Type是XHR的请求,如下图:
# Ajax 案例
需求:在完成用户注册时,当用户名输入框失去焦点时,校验用户名是否在数据库中已存在
# Ajax 案例需求分析
- 前端完成的逻辑
- 给用户名输入框绑定失去焦点事件
onblur
- 发送ajax请求,携带username参数
- 处理响应:是否显示提示信息
- 给用户名输入框绑定失去焦点事件
- 后端完成逻辑
- 接收用户名
- 调用
service
查询User
- 返回标记
整体流程如下:
# Ajax 案例后端实现
在com.itheima.ajax
包下创建SelectUserServlet
:
package com.itheima.ajax;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/selectUserServlet")
public class SelectUserServlet extends HttpServlet {
private UserService userService = new UserService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 接收用户名
String username = request.getParameter("username");
// 2. 调用service查询User对象
User user = userService.getByUsername(username);
boolean flag = false;
if (user != null) {
flag = true;
} else {
flag = false;
}
// 3. 响应数据
response.getWriter().write("" + flag);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Ajax 案例前端实现
将资料中的静态页面拷贝到项目webapp
目录下的ajax
目录中区,并修改CSS样式文件的引用路径,并在页面的body
结束标签前编写JS脚本,在该JS脚本中实现如下逻辑:
- 第一步:给用户名输入框绑定失去焦点事件
onblur
// 1. 给用户输入框绑定失去焦点事件
document.getElementById("username").onblur = function () {};
2
- 第二步:发送Ajax请求,携带
username
参数
// 2. 发送ajax请求
// 2.1 创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.2 发送请求
xhttp.open("GET", "http://localhost/course/selectUserServlet");
xhttp.send();
// 2.3 获取响应数据
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.state == 200) {
// 处理响应结果
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
由于我们发送的是GET请求,所以需要在URL后拼接从输入框获取到的用户名数据,因为我们在第一步绑定失去焦点匿名函数时同构以下代码就可以获取到用户名数据
// 获取用户名的值
var username = this.value; // this: 给哪个对象绑定的时间,this就代表谁
2
而GET请求携带参数就需要将URL修改为:
xhttp.open(
"GET",
"http://localhost/course/selectUserServlet?username=" + username
);
2
3
4
- 第三步:处理响应,根据响应结果判断是否显示提示信息
当this.readyState == 4 && this.state == 200
条件满足时,说明已经Servlet
已经成功响应数据,此时就需要判断响应的数据是否是true
字符串,如果是说明用户名已被占用则需要给出错误提示,如果不是说明未被占用需要清除错误提示。代码如下:
// 判断
if (this.responseText == "true") {
// 用户名已被占用,显示错误提示信息
document.getElementById("username_err").style.display = "";
} else {
// 用户名未被占用,清理掉错误提示信息
document.getElementById("username_err").style.display = "none";
}
2
3
4
5
6
7
8
综上所述,前端完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>欢迎注册</title>
<link href="../css/register.css" rel="stylesheet" />
</head>
<body>
<div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="login.html">登录</a>
</div>
<form id="reg-form" action="#" method="get">
<table>
<tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username" />
<br />
<span id="username_err" class="err_msg" style="display: none"
>用户名不太受欢迎</span
>
</td>
</tr>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password" />
<br />
<span id="password_err" class="err_msg" style="display: none"
>密码格式有误</span
>
</td>
</tr>
<tr>
<td>验证码</td>
<td class="inputs">
<input name="checkCode" type="text" id="checkCode" />
<img src="imgs/a.jpg" />
<a href="#" id="changeImg">看不清?</a>
</td>
</tr>
</table>
<div class="buttons">
<input value="注 册" type="submit" id="reg_btn" />
</div>
<br class="clear" />
</form>
</div>
<script>
// 1. 给用户名输入框绑定失去焦点事件
document.getElementById("username").onblur = function () {
// 2. 发送Ajax请求
// 获取用户名的值
var username = this.value;
// 2.1 创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHttp");
}
// 2.2 发送请求
xhttp.open(
"GET",
"http://localhost/course/selectUserServlet?username=" + username
);
xhttp.send();
// 2.3 获取响应结果
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// 判断
if (this.responseText == "true") {
// 用户名已被占用,显示提示信息
document.getElementById("username_err").style.display = "";
} else {
// 用户名未被占用,清除提示信息
document.getElementById("username_err").style.display = "none";
}
}
};
};
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# Axios
Axios对原生的Ajax进行封装,简化书写。
Axios官网是:https://www.axios-http.cn/
# Axios 基本使用
axios使用是比较简单的,分为以下两步:
- 引入axios的js文件
<script src="../js/axios-0.18.0.js"></script>
使用axios发送请求,并获取响应结果
- 发送get请求
axios({ method: "get", url: "http://localhost/course/selectUserServlet?username=zhangsan", }).then(function (resp) { alert(resp.data); });
1
2
3
4
5
6- 发送post请求
axios({ method: "post", url: "http://localhost/course/selectUserServlet?username=zhangsan", data: "username=zhangsan", }).then(function (resp) { alert(resp.data); });
1
2
3
4
5
6
7
axios()
是用来发送异步请求的,小括号中使用JS对象传递请求相关的参数:
method
属性:用来设置请求方式的,取值为get
或者post
url
属性:用来书写请求的资源路径,如果是get
请求,需要将请求参数拼接到路径的后面,格式为:url?参数名=参数值&参数名2=参数值2
data
属性:作为请求体被发送的数据,也就是说如果是post
请求的话,数据需要作为data
属性的值。
then()
需要传递一个匿名函数,我们将then()
中传递的匿名函数称为回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数,同时该回调函数中的resp
参数是对响应数据进行封装的对象,通过resp.data
可以获取到响应的数据。
# Axios 快速入门
# Axios 后端实现
在com.itheima
下面创建一个包axios
,并在该包下定义一个用于接收请求的AxiosServlet
,代码如下:
package com.itheima.axios;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/axiosServlet")
public class AxiosServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("get ......");
// 1. 接收请求参数
String username = request.getParameter("username");
System.out.println(username);
// 2. 响应数据
response.getWriter().write("hello axios~");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("post ......");
this.doGet(request, response);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Axios 前端实现
在webapp
目录下新建一目录axios
,并在该目录下创建一页面AxiosDemo1.html
- 引入JS文件
<script src="../js/axios-0.18.0.js"></script>
发送Ajax请求
get
请求
axios({ method: "get", url: "http://localhost/course/axiosServlet?username=zhangsan", }).then(function (resp) { alert(resp.data); });
1
2
3
4
5
6post
请求
axios({ method: "post", url: "http://localhost/course/axiosServlet, data: "username=zhangsan" }).then(function(resp) { alert(resp.data); });
1
2
3
4
5
6
7
整体页面代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script src="../js/axios-0.18.0.js"></script>
<script>
// 1. get请求
axios({
method: "get",
url: "http://localhost/course/axiosServlet?username=zhangsan",
}).then(function (resp) {
alert(resp.data);
});
// 2. post请求
axios({
method: "post",
url: "http://localhost/course/axiosServlet",
data: "username=zhangsan",
}).then(function (resp) {
alert(resp.data);
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Axios 请求方法别名
为了方便起见,Axios已经为所有支持的请求方法提供了别名,如下:
get
请求:axios.get(url [, config])
delete
请求:axios.get(url [, config])
head
请求:axios.head[url [, config])
options
请求:axios.option(url [, config])
post
请求:axios.post(url [, data] [, config])
put
请求:axios.put(url [, data] [, config])
patch
请求:axios.patch(url [, data] [, config])
我们重点关注下get
和post
请求即可,这两种方式是最常用的。比如:入门案例中的get
请求代码可以修改为如下:
axios
.get("http://localhost/course/axiosServlet?username=zhangsan")
.then(function (resp) {
alert(resp.data);
});
2
3
4
5
入门案例中的post
请求代码可以修改为:
axios
.post("http://localhost/course/axiosServlet", "username=zhangsan")
.then(function (resp) {
alert(resp.data);
});
2
3
4
5
# JSON
# JSON 概述
概念:JavaScript Object Notation,JavaScript对象表示法。
如下是JavaScript对象的定义格式:
{
name: "zhangsan",
age: 23,
city: "北京"
}
2
3
4
5
接下来我们来看看JSON的格式:
{
"name": "zhangsan",
"age": 23,
"city": "北京"
}
2
3
4
5
通过上面JS对象格式和JSON格式进行对比,发现两个格式特别相似,只不过JS对象中的属性名没有用上引号括起来,而属性值方面JS可以使用单引号也可以使用双引号,但JSON要去必须使用双引号,这是JSON格式的规定。那么,JSON格式的数据有什么作用呢?
作用:由于JSON语法格式简单,层次结构鲜明,现在多用于作为数据载体,在网络中进行数据传输。比如下面的代码是服务器给浏览器响应的数据,这个数据比较简单,但是如果需要将Java对象中封装的数据响应给浏览器的话,应该以何种数据传输呢?
// 响应数据
response.getWriter().write("hello axios~");
2
大家应该还记得Ajax的概念吧?JavaScript和XML,这里的XML就是以前进行数据传递的方式,如下:
<student>
<name>张三</name>
<age>23</age>
<city>北京</city>
</student>
2
3
4
5
再来看JSON描述以上数据的写法:
{
"name": "张三",
"age": 23,
"city": "北京"
}
2
3
4
5
上面两种格式进行对比下我们就能发现,JSON格式数据比较简单,而且占的字节数更少。
# JSON 基础语法
# JSON 定义格式
JSON本质就是一个字符串,但是该字符串内容是有一定的格式要求的,定义格式如下:
var 变量名 = '{"key": value, "key": value, ...}';
JSON串的键要求必须使用双引号括起来,而值根据要表示的类型确定,value
的数据类型如下:
- 数字(整数或浮点数)
- 字符串(使用双引号括起来)
- 逻辑值(
true
或者false
) - 数组(在方括号中)
- 对象(在花括号中)
null
示例:
var jsonStr =
'{"name": "zhangsan", "age": 23, "addr": ["北京", "上海", "西安"]}';
2
# JSON 代码演示
创建一个页面,在该页面的<script>
标签中定义JSON字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
// 1. 定义JSON字符串
var jsonStr =
'{"name": "zhangsan", "age": 23, "addr": ["北京", "上海", "西安"]}';
alert(jsonStr);
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
通过浏览器打开,页面效果如下:
那么现在我们需要获取JSON串中的name
属性值,该怎么处理呢?
如果它是一个JS对象,我们就可以通过js对象.属性名
的方式来获取数据。JS提供了一个对象JSON,该对象有如下两个方法:
parse(str)
:将JSON串转换为JS对象,使用方式为:var jsObject = JSON.parse(jsonStr);
stringfy(obj)
:将JS对象转换为JSON串,使用方式是:var jsonStr = JSON.stringify(jsObject)
代码演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
// 1. 定义JSON字符串
var jsonStr =
'{"name": "zhangsan", "age": 23, "addr": ["北京", "上海", "西安"]}';
alert(jsonStr);
// 2. 将JSON字符串转为JS对象
let jsObject = JSON.parse(jsonStr);
alert(jsObject);
alert(jsObject.name);
// 3. 将JS对象转换为JSON字符串
let jsonStr2 = JSON.stringify(jsObject);
alert(jsonStr2);
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 发送异步请求携带参数
后面我们使用axios
发送请求时,如果要携带复杂的数据时就会以JSON格式进行传递,如下:
axios({
method: "post",
url: "http://localhost/course/selectUserServlet",
data: "username=zhangsan",
}).then(function (resp) {
alert(resp.data);
});
2
3
4
5
6
7
请求参数不可能由我们自己拼接字符串吧?这样写会很繁琐,学习了JSON,我们就可以提前定义一个JS对象,用来封装需要提交的参数,然后使用JSON.stringfy(js对象)
转换为JSON串,再将该JSON串作为axios
的data
属性值进行请求参数的提交。如下:
var jsObject = { name: "张三" };
axios({
method: "post",
url: "http://localhost/course/selectUserServlet",
data: JSON.stringfy(jsObject),
}).then(function (resp) {
alert(resp.data);
});
2
3
4
5
6
7
8
9
而axios
是一个很强大的工具,我们只需要将需要提交的参数封装成JS对象,并将该JS对象作为axios
的data
属性值即可,他会自动将JS对象转换为JSON串进行提交。如下:
var jsObject = { name: "张三" };
axios({
method: "post",
url: "http://localhost/course/selectUserServlet",
data: jsObject, // 这里axios会将该js对象转换为json串
}).then(function (resp) {
alert(resp.data);
});
2
3
4
5
6
7
8
9
注意
- JS提供的JSON对象我们只需要了解一下即可,因为
axios
会自动对JS对象和JSON串进行相互转换 - 发送异步请求时,如果请求参数是JSON格式,那请求必须是POST,因为JSON串需要放在请求体中。
# JSON 串和 Java 对象的相互转换
学习完JSON后,接下来我们就要看下JSON的作用,后面我们会以JSON格式的数据进行前后端交互,前端发送请求时,如果是复杂的数据就会以JSON提交给后端,而后端如果需要响应一些复杂的数据时,也需要以JSON格式将数据响应回给浏览器。
在后端我们就需要重点学习下面两部分操作:
- 请求数据:JSON字符串转为Java对象
- 响应数据:Java对象转为JSON字符串
接下来给大家介绍一套API,可以实现上面两部分操作,这套API就是Fastjson
# Fastjson 概述
Fastjson是阿里巴巴提供的一个Java语言编写的高性能功能完善的JSON库,是目前Java语言中最快的JSON库,可以实现Java对象和JSON字符串的相互转换。
# Fastjson 作用
Fastjson使用也是比较简单,分为一下三步完成
- 导入坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
2
3
4
5
- Java 对象转 JSON
String jsonStr = JSON.toJSONString(obj);
将Java对象转换为JSON串,只需要使用Fastjson提供的JSON
类中的toJSONString()
静态方法即可。
- JSON 字符串转 Java 对象
User user = JSON.parseObject(jsonStr, User.class);
将JSON转换为Java对象,只需要使用Fastjson提供的JSON
类中的parseObject()
静态方法即可。
# Fastjson 代码演示
引入坐标
创建一个类,用来测试Java对象和JSON串的相互转换,代码如下:
package com.itheima.json;
import com.alibaba.fastjson.JSON;
import com.itheima.pojo.User;
import org.junit.Test;
public class FastJsonTest {
@Test
public void testJava2Json() {
// 将Java对象转为JSON字符串
User user = new User();
user.setId(1);
user.setUsername("zhangsan");
user.setPassword("123");
String jsonString = JSON.toJSONString(user);
System.out.println(jsonString);
}
@Test
public void testJson2Java() {
// 将JSON字符串转为Java对象
String jsonStr = "{\"id\": 1, \"password\": \"123\", \"username\": \"zhangsan\"}";
User u = JSON.parseObject(jsonStr, User.class);
System.out.println(u);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 案例
# 案例需求
使用Axios + JSON完成品牌列表数据查询和添加,页面效果还是下图所示
# 查询所有功能
如上图所示就是该功能的整体流程,前后端需要以JSON格式进行数据的传递,由于此功能是查询所有的功能,前端发送Ajax请求不需要携带参数,而后端需响应如下格式的JSON数据
[
{
"brandName": "三只松鼠",
"companyName": "三只松鼠股份有限公司",
"description": "好吃不上火",
"id": 1,
"ordered": 5,
"status": 0
},
{
"brandName": "华为",
"companyName": "华为技术有限公司",
"description": "华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界",
"id": 2,
"ordered": 100,
"status": 1
},
{
"brandName": "小米",
"companyName": "小米科技有限公司",
"description": "are you ok",
"id": 3,
"ordered": 50,
"status": 1
},
{
"brandName": "联想",
"companyName": "联想",
"description": "联想联想联想联想联想联想联想联想",
"id": 5,
"ordered": 3,
"status": 0
},
{
"brandName": "外星人测试修改",
"companyName": "外星人外星人测试修改",
"description": "外星人外星人外星人外星人外星人外星人外星人\r\n外星人测试修改\r\n外星人测试修改",
"id": 6,
"ordered": 210,
"status": 0
},
{
"brandName": "123",
"companyName": "123",
"description": "12312",
"id": 7,
"ordered": 1,
"status": 0
},
{
"brandName": "Thinkpad",
"companyName": "Thinkpad",
"description": "ThinkpadThinkpadThinkpadThinkpad",
"id": 8,
"ordered": 5,
"status": 1
}
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 环境准备
将课程资料中的Java代码、HTML以及JS文件拷贝到我们的工作空间中,工程目录结构如下:
注意
- 在给定的原始工程中已经给了一些代码实现,下面我们在案例中只关注前后端交互代码的实现
- 根据自己的数据库环境修改数据库连接信息,在
mybatis-config.xml
核心配置文件中修改
# 查询所有后端实现
在com.itheima.web
包下创建SelectAllServlet
,具体业务逻辑如下:
调用
service
的selectAll()
方法进行查询所有品牌将查询到的集合数据转换为JSON数据,此过程我们称之为序列化,如果将JSON数据转换为Java对象,我们称之为反序列化。
将JSON数据响应给浏览器,这里一定要设置响应数据的类型和字符集
response.setContentType("text/json;charset=utf-8");
1
SelectAllServlet
代码如下:
package com.itheima.web;
import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
private BrandService brandService = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 调用Service查询
List<Brand> brands = brandService.selectAll();
// 2. 将集合转换为JSON数据 序列化
String jsonString = JSON.toJSONString(brands);
// 3. 响应数据 application/json text/json
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(jsonString);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 查询所有前端实现
- 引入JS文件
在brand.html
页面引入axios
的JS文件
<script src="js/axios-0.18.0.js"></script>
- 绑定页面加载完毕事件
在brand.html
页面绑定加载完毕事件,该时间是在页面加载完毕后被触发,代码如下:
window.onload = function () {};
- 发送异步请求
在页面加载完毕事件绑定的匿名函数中发送异步请求,代码如下:
// 发送ajax请求
axios({
method: "get",
url: "http://localhost/course/selectAllServlet",
}).then(function (resp) {});
2
3
4
5
- 处理响应数据
在then
中的回调函数中通过resp.data
可以获取响应回来的数据,数据格式如下:
[
{
"brandName": "三只松鼠",
"companyName": "三只松鼠股份有限公司",
"description": "好吃不上火",
"id": 1,
"ordered": 5,
"status": 0
},
{
"brandName": "华为",
"companyName": "华为技术有限公司",
"description": "华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界",
"id": 2,
"ordered": 100,
"status": 1
},
{
"brandName": "小米",
"companyName": "小米科技有限公司",
"description": "are you ok",
"id": 3,
"ordered": 50,
"status": 1
},
{
"brandName": "联想",
"companyName": "联想",
"description": "联想联想联想联想联想联想联想联想",
"id": 5,
"ordered": 3,
"status": 0
},
{
"brandName": "外星人测试修改",
"companyName": "外星人外星人测试修改",
"description": "外星人外星人外星人外星人外星人外星人外星人\r\n外星人测试修改\r\n外星人测试修改",
"id": 6,
"ordered": 210,
"status": 0
},
{
"brandName": "123",
"companyName": "123",
"description": "12312",
"id": 7,
"ordered": 1,
"status": 0
},
{
"brandName": "Thinkpad",
"companyName": "Thinkpad",
"description": "ThinkpadThinkpadThinkpadThinkpad",
"id": 8,
"ordered": 5,
"status": 1
}
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
获取到响应数据后,我们就需要拼接字符串,将下面表格中的所有的tr
拼接到一个字符串中,然后使用
document.getElementById("brandTable").innerHTML = 拼接好的字符串;
就可以动态的展示出用户想看到的数据了。
表头行是固定的,所以先定义初始值是表头行数据的字符串,如下:
// 获取数据
let brands = resp.data;
let tableData =
"<tr>\n" +
" <th>序号</th>\n" +
" <th>品牌名称</th>\n" +
" <th>企业名称</th>\n" +
" <th>排序</th>\n" +
" <th>品牌介绍</th>\n" +
" <th>状态</th>\n" +
" <th>操作</th>\n" +
"</tr>";
2
3
4
5
6
7
8
9
10
11
12
接下来遍历响应回来的数据brands
,拿到每一个品牌的数据
for (let i = 0; i < brands.length; i++) {
let brand = brands[i];
}
2
3
紧接着就是从brand
对象中获取数据并拼接数据行,累加到tableData
字符串变量中
tableData +=
"\n" +
'<tr align="center">\n' +
" <td>" +
(i + 1) +
"</td>\n" +
" <td>" +
brand.brandName +
"</td>\n" +
" <td>" +
brand.companyName +
"</td>\n" +
" <td>" +
brand.ordered +
"</td>\n" +
" <td>" +
brand.description +
"</td>\n" +
" <td>" +
brand.status +
"</td>\n" +
"\n" +
' <td><a href="#">修改</a><a href="#">删除</a></td>\n' +
"</tr>";
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
最后再将拼接好的字符串写到表格中
// 设置表格数据
document.getElementById("brandTable").innerHTML = tableData;
2
整体页面代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="addBrand.html"><input type="button" value="新增"></a><br>
<hr>
<table id="brandTable" border="1" cellspacing="0" width="100%">
</table>
<script src="js/axios-0.18.0.js"></script>
<script>
//1. 当页面加载完成后,发送ajax请求
window.onload = function () {
//2. 发送ajax请求
axios({
method:"get",
url:"http://localhost/course/selectAllServlet"
}).then(function (resp) {
//获取数据
let brands = resp.data;
let tableData = " <tr>\n" +
" <th>序号</th>\n" +
" <th>品牌名称</th>\n" +
" <th>企业名称</th>\n" +
" <th>排序</th>\n" +
" <th>品牌介绍</th>\n" +
" <th>状态</th>\n" +
" <th>操作</th>\n" +
" </tr>";
for (let i = 0; i < brands.length ; i++) {
let brand = brands[i];
tableData += "\n" +
" <tr align=\"center\">\n" +
" <td>"+(i+1)+"</td>\n" +
" <td>"+brand.brandName+"</td>\n" +
" <td>"+brand.companyName+"</td>\n" +
" <td>"+brand.ordered+"</td>\n" +
" <td>"+brand.description+"</td>\n" +
" <td>"+brand.status+"</td>\n" +
"\n" +
" <td><a href=\"#\">修改</a> <a href=\"#\">删除</a></td>\n" +
" </tr>";
}
// 设置表格数据
document.getElementById("brandTable").innerHTML = tableData;
})
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 添加品牌功能
如上图所示,当我们点击新增按钮,会跳转到addBrand.html
页面,在addBrand.html
页面输入数据后点击提交按钮,就会将数据提交到后端。
具体的前后端交互流程如下图所示:
说明
前端需要将用户输入的数据提交到后端,这部分数据需要以JSON格式进行提交,数据格式如下:
{
"brandName":"汇源",
"companyName":"汇源",
"ordered":"123",
"description":"汇源果汁",
"status":"1"
}
2
3
4
5
6
7
# 添加后端实现
在com.itheima.web
包下创建AddServlet
,具体业务逻辑如下:
- 获取请求参数:由于前端提交的数据格式是JSON,所以我们不能使用
request.getParameter()
方法获取请求参数- 如果提交的数据格式是
username=zhangsan&age=23
这样的,后端就可以使用request.getParameter()
方法获取 - 如果提交的数据格式是JSON,后端就需要通过
request
对象获取输入流,再通过输入流读取数据
- 如果提交的数据格式是
- 将获取到的请求参数(JSON格式的数据)转换为
Brand
对象 - 调用
BrandService
的add
方法进行数据的添加操作 - 将JSON数据响应返回给浏览器
AddServlet
代码如下:
package com.itheima.web;
import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
private BrandService brandService = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 接收数据,request.getParameter不能接收json格式的数据
// 1.1 获取请求体数据
BufferedReader reader = request.getReader();
String params = reader.readLine();
// 1.2 将JSON字符串转为Java对象
Brand brand = JSON.parseObject(params, Brand.class);
// 2. 调用BrandService的添加方法
brandService.add(brand);
// 3. 响应成功标识
response.getWriter().write("success");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 添加前端实现
在addBrand.html
页面给提交按钮绑定点击事件,并在绑定的匿名函数中发送异步请求,代码如下:
// 1. 给按钮绑定单击事件
document.getElementById("btn").onclick = function() {
// 2. 发送ajax请求
axios({
method: "post",
url: "http://localhost/course/addServlet",
data: ???
}).then(function(resp) {
// 判断响应数据是否为success
if (resp.data == "success") {
location.href = "http://localhost/course/brand.html";
}
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
现在我们只需要考虑如何获取页面上用户输入的数据即可。
首先我们先定义如下的一个JS对象,该对象是用来封装页面上输入的数据,并将该对象作为上面发送异步请求时data
属性的值:
// 将表单数据转换为json
var formData = {
brandName: "",
companyName: "",
ordered: "",
description: "",
status: ""
}
2
3
4
5
6
7
8
接下来获取输入框输入的数据,并将获取到的数据赋值给formData
对象指定的属性,比如获取品牌名的输入框数据,并把该数据赋值给formData
对象的brandName
属性
// 获取表单数据
let brandName = document.getElementById("brandName").value;
// 设置数据
formData.brandName = brandName;
2
3
4
说明
其他输入框都采用同样的方式获取并赋值,但是有一个比较特殊,就是状态数据:
<input type="radio" name="status" value="0"> 禁用
<input type="radio" name="status" value="1"> 启用 <br>
2
我们需要判断哪个被选中了,再将选中的单选框数据赋值给formData
对象的status
属性,代码如下:
let status = document.getElementsByName("status");
for (let i = 0; i < status.length; i++) {
if (status[i].checked) {
formData.status = status[i].value;
}
}
2
3
4
5
6
整体页面代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加品牌</title>
</head>
<body>
<h3>添加品牌</h3>
<form action="" method="post">
品牌名称:<input id="brandName" name="brandName"><br>
企业名称:<input id="companyName" name="companyName"><br>
排序:<input id="ordered" name="ordered"><br>
描述信息:<textarea rows="5" cols="20" id="description" name="description"></textarea><br>
状态:
<input type="radio" name="status" value="0">禁用
<input type="radio" name="status" value="1">启用<br>
<input type="button" id="btn" value="提交">
</form>
<script src="js/axios-0.18.0.js"></script>
<script>
// 1. 给按钮绑定单击事件
document.getElementById("btn").onclick = function() {
// 将表单数据转换为json
var formData = {
brandName: "",
companyName: "",
ordered: "",
description: "",
status: ""
}
// 获取表单品牌名数据
let brandName = document.getElementById("brandName").value;
// 设置品牌名
formData.brandName = brandName;
// 获取并设置企业名称
let companyName = document.getElementById("companyName").value;
formData.companyName = companyName;
// 获取并设置排序
let ordered = document.getElementById("ordered").value;
formData.ordered = ordered;
// 获取并设置描述信息
let description = document.getElementById("description").value;
formData.description = description;
// 获取并设置状态数据
let status = document.getElementsByName("status");
for (let i = 0; i < status.length; i++) {
if (status[i].checked) {
formData.status = status[i].value;
}
}
// 2. 发送ajax请求
axios({
method: "post",
url: "http://localhost/course/addServlet",
data: formData
}).then(function(resp) {
// 判断响应数据是否为success
if (resp.data == "success") {
location.href = "http://localhost/course/brand.html";
}
})
}
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
说明
查询所有 和 添加品牌 功能至此就全部实现了,现在大家肯定会觉得前端代码很复杂,不过这只是暂时的,后面学习vue前端框架后,这部分前端代码就可以进行很大程度的简化。