[TOC]
AJAX&JSON
# 前端增强3天
1. ajax + json
2. vue + elementui
3. vue脚手架
# 综合案例2天
1. 第一天: 布置需求,自己做
2. 第二天: 实现,优化
一. AJAX的概述
# 同步和异步
1. 同步: 执行完A,才能执行B (类似java单线程) synchronous
同步锁(synchronized)
2. 异步: A还没执行完,B就可以执行 (类似java多线程) Asynchronous
# 同步请求和异步请求
1. 同步请求: 同步请求响应的结果会刷新整个网页
因为同步请求结果刷新整个网页,直到这个请求结束之前,用户不能执行别的操作
比如163邮箱的注册功能,当用户填完信息,点击注册时
整个网页发生跳转(地址栏的地址改变)
2. 异步请求: 异步请求响应的结果可以只更新局部网页
163邮箱注册页面,有个检测邮箱地址是否可用功能
前端数据校验
1. 前端校验 : 只需要前端就可以独立校验(比如长度限制,邮箱格式是否正确)
2. 后端校验 : 需要后端参与的校验 (前端需要发起请求)
网页不会跳转(地址栏不会发生改变)
# 结论
1. 异步请求是现在前端主要请求类型
相对同步请求来说: 效率高,体验好
2. 我们之前所学习的所有前端发起的请求都是属于同步请求
3. 异步请求今天才学习(ajax)
1.1 什么是ajax
**异步JavaScript和XML (Asynchronous Javascript And XML)**
# ajax : 是js中发起异步请求的技术
1. 异步的访问方式
2. 使用到的技术:JavaScript和XML
1). JavaScript:ajax是js的异步请求技术
2). XML:用于封装服务器发送的大量的数据,因为XML无关的数据太多,而且解析比较麻烦。所以目前几乎不再使用了,使用JSON格式来代替。
1.2 同步和异步的区别
# 同步方式
1. 浏览器与服务器是串行的操作,浏览器发起请求的时候,服务器在处理该请求的时候,浏览器只能等待。以前使用JSP开发的方式都是同步的方式。
2. 缺点:执行效率低,用户体验差。
# 异步方式
1. 浏览器与服务器是并行工作的
2. 优点:执行效率高,用户体验更好。
1.3 AJAX的应用场景
1.3.1 检查用户名是否已被注册
很多站点的注册页面都具备自动检测用户名是否存在的友好提示,该功能整体页面并没有刷新,但仍然可以异步与服务器端进行数据交换,查询用户的输入的用户名是否在数据库中已经存在。
1.3.2 内容自动补全
百度的搜索补全功能:
京东的搜索补全功能:
二. Ajax异步请求库 axios (重要!!!)
2.1 axios介绍
- 原生ajax请求的代码编写太过繁琐,我们可以使用axios这个库来简化操作!
在后续学习的Vue(前端框架)中发送异步请求,使用的就是axios.
需要注意的是axios不是vue的插件,它可以独立使用.
- 使用步骤
1.引入axios核心js文件。
2.调用axios对象的方法来发起异步请求。
3.调用axios对象的方法来处理响应的数据。 axios常用方法
#备注: then函数的参数response是一个json对象,我们重点只需要了解response.data即可 { // `data` 由服务器提供的响应体 (重要!) data: {}, // `status` 来自服务器响应的 HTTP 状态码 status: 200, // `statusText` 来自服务器响应的 HTTP 状态信息 statusText: 'OK', // `headers` 服务器响应的头 headers: {}, // `config` 是为请求提供的配置信息 config: {} }
- 代码实现
- html代码
```html
<!DOCTYPE html>
``` - **java代码** ```java package com.itheima01.ajax; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/MyServlet") public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 接收请求 String name = request.getParameter("name"); String age = request.getParameter("age"); //2. 业务处理 System.out.println(name + "," + age); //3. 响应 //响应体输出流 response.getWriter().print("hello"); } } ``` ### 2.2 检查用户名是否已被注册 ```markdown #需求: a. 有一个注册的表单, 有注册用户名和密码,一个提交按钮 b. 用户名输完之后,检测这个用户名是否可用 c. 需要发起请求,并且响应的结果局部更新网页 -> 异步 #分析: 1. 用户名输入框注册一个失去焦点事件(onblur) 2. 向服务器发送 异步 请求 3. 服务器响应之后, 提示信息 局部更新到页面上 ``` ```html注册页面
``` ```java package com.itheima01.ajax; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/CheckServlet") public class CheckServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 接收请求 request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); //2. 业务处理 //判断用户名是否存在 : 理论上是需要查询数据库,现在用伪数据 boolean result = false; if("jack".equals(username)){ result = true; //表示已存在 } //3. 响应 response.getWriter().print(result); } } ``` ## 三. JSON ### 3.1 JSON概述 JavaScript对象文本表示形式(JavaScript Object Notation : js对象简谱) > json是js对象,但是js对象不一定是json > json是目前 前后端数据交互的主要格式之一 ```markdown * java对象表示形式 User user = new User(); user.setUsername("后羿"); user.setAge(23); user.setSex("男"); ... Product product = new Product(); product.setName("小米10"); product.setDesc("1亿像素的手机小王子"); * javaScript对象表示形式 let user ={"username":"后羿","age":23,"sex":"男"} let product = {"name":"小米10","desc":"1亿像素的手机小王子"} ``` json可以取代XML笨重的数据结构,和xml相比:更小、更快,更易解析 > json、xml作用:作为数据的载体,在网络中传输  ### 3.2 JSON基础语法 > json是一种特殊的 js 对象 ```markdown # json的语法主要有两种: 1. 对象 { } 2. 数组 [ ] 1. 对象类型 {name:value,name:value} 2. 数组类型 [ {name:value,name:value}, {name:value,name:value}, {name:value,name:value} ] 3. 复杂对象 { name:value, wives:[{name:value},{},{}], son:{name:value} } # 注意: 1. value必须是以下数据类型之一: 字符串 数字 对象(JSON 对象) 数组 布尔 Null 2. JSON 中的字符串必须用双引号包围。(单引号不行!) 3. JSON的name在js中可以省略双引号,但是在其他语言比如java不能省略 # 验证 : 百度搜索json (https://www.json.cn/) ``` ```html ``` ## 四. Fastjson ### 4.1 fastjson引入 **需求** 在服务器端有如下User对象需要响应给浏览器. 为了方便浏览器解析, 这就要求服务端在响应之前,需要将转成符合Json格式的字符串. ```java package com.itheima02.json; public class User { private String username; private String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}'; } //TODO: 自己采用字符串拼接的方式输出。 public String toJson() { return "{\"username\":\""+username+"\",\"password\":"+password+"}"; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } ``` 通过拼接字符串的形式,将java对象转换成json格式字符串无疑是非常麻烦的,在开发中我们一般使用转换工具来达到实现. 所谓的转换工具是通过java封装好的一些jar工具包,可以直接将java对象或集合转换成json格式的字符串。 **常见的json转换工具**  > 其实这些工具使用起来都差不多, 目前我们学习使用的是Fastjson ### 4.2 fastjson 常用 API **fastjson 作用:** 1. 将java对象(PO)转成json字符串 2. 将json字符串 转成 java对象(VO) **常用API** fastjson API 入口类是`com.alibaba.fastjson.JSON`,常用的序列化操作都可以在`JSON`类上的静态方法直接完成。 ```java public static final String toJSONString(Object object); // 将JavaBean序列化为JSON文本 public static finalT parseObject(String text, Class clazz); // 把JSON文本解析成指定类型JavaBean public static final List parseArray(String text, Class clazz); //把JSON文本解析成JavaBean集合 ``` ### 4.3 fastjson 使用实例 #### 4.3.1 导包 ```xml com.alibaba fastjson 1.2.47 list = new ArrayList<>(); list.add(new User("zs","110")); list.add(new User("ls","120")); list.add(new User("ww","119")); String json = JSON.toJSONString(list); //[{"password":"110","username":"zs"},{"password":"120","username":"ls"},{"password":"119","username":"ww"}] System.out.println(json); } @Test public void method04(){ String json = "{\"password\":\"123\",\"username\":\"ww\"}"; System.out.println(json); User user = JSON.parseObject(json, User.class); // User{username='ww', password='123'} System.out.println(user); } @Test public void method05(){ String json = "[{\"password\":\"110\",\"username\":\"zs\"},{\"password\":\"120\",\"username\":\"ls\"},{\"password\":\"119\",\"username\":\"ww\"}]"; List list = JSON.parseArray(json, User.class); //[User{username='zs', password='110'}, User{username='ls', password='120'}, User{username='ww', password='119'}] System.out.println(list); } } ``` ## 五. ajax和json综合 (特别重要!!!) ### 5.1 请求参数和响应数据都是普通字符串 ```html ajax和json综合
```java @WebServlet("/Union01Servlet") public class Union01Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 接收请求 request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username + "," + password); //2. 业务处理 //3. 响应 response.getWriter().print("hello"); } }
5.2 响应数据改成json格式
响应结果的封装
package com.itheima03.union; //数据封装 public class Result { //表示状态: true表示成功 private boolean flag; // 提示信息 private String msg; // 数据 private Object data; public Result() { } public Result(boolean flag, String msg, Object data) { this.flag = flag; this.msg = msg; this.data = data; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } }
package com.itheima03.union; /* pojo: 映射数据表 */ public class Friend { private Integer id; private String name; public Friend() { } //为了方便设置伪数据 public Friend(Integer id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "Friend{" + "id=" + id + ", name='" + name + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>ajax和json综合</h1> <!-- 前端js: axios (封装了ajax的请求库) 后端java: fastjson (json和java对象转换) --> <!-- ajax : 异步请求 json : 作为异步请求中, 前后端数据传递的主要格式 1). 请求 : 浏览器发送给服务器的数据 2). 响应 : 服务器发送给浏览器的数据 普通字符串 json格式 --> <input type="button" value="请求和响应都是普通字符串" onclick="method01()"> <br> <input type="button" value="响应数据改成json字符串" onclick="method02()"> <br> <input type="button" value="请求数据也改成json字符串" onclick="method03()"> <br> </body> <script src="js/axios-0.18.0.js"></script> <script> function method01(){ let url = "Union01Servlet" let param = "username=zs&password=123" axios.post(url,param).then(response=>{ console.log(response.data); }) } </script> <script> function method02(){ let url = "Union02Servlet" let param = "username=zs&password=123" axios.post(url,param).then(response=>{ console.log(response.data); }) } </script> </html>
package com.itheima03.union; import com.alibaba.fastjson.JSON; 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.ArrayList; @WebServlet("/Union02Servlet") public class Union02Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //1. 接收请求 //post请求参数乱码解决 request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username + "," + password); //2. 业务处理 : 从数据库中查询此用户所有的好友 (这里访问数据库,可能出现异常) int i = 1/0; ArrayList<Friend> list = new ArrayList<>(); list.add(new Friend(1,"瘪三")); list.add(new Friend(2,"狗蛋")); list.add(new Friend(3,"二丫")); //3. 响应 Result result = new Result(true, "成功", list); //java对象转换json格式字符串 String json = JSON.toJSONString(result); // 解决响应体中文乱码问题 // response.setContentType("text/html;charset=utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().print(json); } catch (Exception e) { Result result = new Result(false, "服务器当前比较繁忙,请稍后再访问", null); String json = JSON.toJSONString(result); response.setContentType("application/json;charset=utf-8"); response.getWriter().print(json); } } }
5.3 请求参数改成json格式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>ajax和json综合</h1> <!-- 前端js: axios (封装了ajax的请求库) 后端java: fastjson (json和java对象转换) --> <!-- ajax : 异步请求 json : 作为异步请求中, 前后端数据传递的主要格式 1). 请求 : 浏览器发送给服务器的数据 (请求参数) url格式 : name=value&name=value json格式 : {name : value,name : value} 2). 响应 : 服务器发送给浏览器的数据 (响应体) 普通字符串 json格式 --> <input type="button" value="请求和响应都是普通字符串" onclick="method01()"> <br> <input type="button" value="响应数据改成json字符串" onclick="method02()"> <br> <input type="button" value="请求数据也改成json字符串" onclick="method03()"> <br> </body> <script src="js/axios-0.18.0.js"></script> <script> function method01(){ let url = "Union01Servlet" let param = "username=zs&password=123" axios.post(url,param).then(response=>{ console.log(response.data); }) } </script> <script> function method02(){ let url = "Union02Servlet" let param = "username=zs&password=123" axios.post(url,param).then(response=>{ console.log(response.data); }) } </script> <script> function method03(){ let url = "Union03Servlet" // let param = "username=zs&password=123" let param = { username : "ww", password : "110" } axios.post(url,param).then(response=>{ console.log(response.data); }) } </script> </html>
package com.itheima03.union; public class User { private String username; private String password; @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}'; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package com.itheima03.union; import com.alibaba.fastjson.JSON; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; 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.ArrayList; /* TODO: 接收请求参数 1. url格式 -> username=zs //只识别url格式的参数 String username = request.getParameter("username"); 2. json格式 -> {username : "ls"} 1). 通过以上的api获取不到 2). 采用原生方式 : 分析 比如post请求参数放在请求体中 先获取请求体数据 : 对java来说,json格式字符串 将json格式字符串转换成java对象 */ @WebServlet("/Union03Servlet") public class Union03Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //1. 接收请求 //post请求参数乱码解决 // request.setCharacterEncoding("utf-8"); // String username = request.getParameter("username"); // String password = request.getParameter("password"); // System.out.println(username + "," + password); //获取请求体输入流 : 包含了post请求参数 /* ServletInputStream is = request.getInputStream(); byte[] buffer = new byte[1024]; int length; while((length = is.read(buffer)) != -1){ String str = new String(buffer, 0, length); System.out.println(str); User user = JSON.parseObject(str, User.class); System.out.println(user); }*/ //获取请求体输入流 : 包含了post请求参数 ServletInputStream is = request.getInputStream(); //将输入流中的json格式字符串转换成user对象 Object o = JSON.parseObject(is, User.class); System.out.println(o); //2. 业务处理 : 从数据库中查询此用户所有的好友 (这里访问数据库,可能出现异常) // int i = 1/0; ArrayList<Friend> list = new ArrayList<>(); list.add(new Friend(1,"瘪三")); list.add(new Friend(2,"狗蛋")); list.add(new Friend(3,"二丫")); //3. 响应 Result result = new Result(true, "成功", list); //java对象转换json格式字符串 String json = JSON.toJSONString(result); // 解决响应体中文乱码问题 // response.setContentType("text/html;charset=utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().print(json); } catch (Exception e) { //3. 响应 Result result = new Result(false, "服务器当前比较繁忙,请稍后再访问", null); String json = JSON.toJSONString(result); response.setContentType("application/json;charset=utf-8"); response.getWriter().print(json); } } }
5.4 抽取BaseController
package com.itheima03.union; import com.alibaba.fastjson.JSON; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; //将获取请求和响应进行封装 public class BaseController { //第一个方法的作用: 将请求体中的数据转换成指定类型的对象 //泛型方法 public static <T>T getBean(HttpServletRequest request,Class<T> clazz) throws IOException { ServletInputStream is = request.getInputStream(); //将输入流中的json格式字符串转换成user对象 T o = JSON.parseObject(is, clazz); return o; } //第二个方法的作用: 将result对象转成json格式字符串并响应 public static void printResult(HttpServletResponse response,Result result) throws IOException { String json = JSON.toJSONString(result); // 解决响应体中文乱码问题 response.setContentType("application/json;charset=utf-8"); response.getWriter().print(json); } }
package com.itheima03.union; import com.alibaba.fastjson.JSON; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; 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.ArrayList; @WebServlet("/Union04Servlet") public class Union04Servlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Result result; try { //1. 接收请求 //获取请求体输入流 : 包含了post请求参数 // ServletInputStream is = request.getInputStream(); // Object o = JSON.parseObject(is, User.class); // System.out.println(o); // Object bean = BaseController.getBean(request,User.class); // User bean = (User) BaseController.getBean(request,User.class); User bean = BaseController.getBean(request, User.class); System.out.println(bean); //2. 业务处理 : 从数据库中查询此用户所有的好友 (这里访问数据库,可能出现异常) // int i = 1/0; ArrayList<Friend> list = new ArrayList<>(); list.add(new Friend(1,"瘪三")); list.add(new Friend(2,"狗蛋")); list.add(new Friend(3,"二丫")); //3. 响应 result = new Result(true, "成功", list); // BaseController.printResult(response,result); } catch (Exception e) { //3. 响应 result = new Result(false, "服务器当前比较繁忙,请稍后再访问", null); // BaseController.printResult(response,result); } BaseController.printResult(response,result); } }
- html代码
```html
<!DOCTYPE html>