Ajax
服务器渲染
点击超链接【浏览器窗口】——>发送请求——>servlet——>Thymeleaf——>服务器端渲染,完整页面:HTML格式的数据——>响应——>浏览器窗口内容整体被响应数据的完整页面所替换【浏览器窗口】
Ajax渲染【局部更新】
Ajax程序发出请求【触发函数】——Servlet——数据片段【JSON格式的数据】——响应——Ajax程序获得响应数据——Ajax程序修改页面局部
前后端分离
真正的前后端分离式前端项目和后端项目分服务器部署,在这里先理解为彻底舍弃服务器端渲染,数据全部通过Ajax方式以JSON格式来传递。
同步和异步的区别
Ajax本身就是Asynchronous JavaScript And XML的缩写,直译为:异步的JavaScript和XML。在实际应用中Ajax指的是:不刷新浏览器窗口,不做页面跳转,局部更新页面内容的技术。
同步
多个操作按顺序执行,前面的发操作没有完成,后面的操作就必须等待,所以操作通常是串行的。【如服务器渲染】
异步
多个操作相继并发执行,即使开始的先后顺序不同,但是由于他们各自实在自己独立的进程或线程中完成,所以互不干扰,谁也不用等待谁。【如Ajax渲染】
应用场景
- 网站首页使用Ajax加载数据,可以提高页面响应效率;
- 搜索框、文本框中使用Ajax检索数据,可以提高用户体验度;
- ...
语法
原生的Js发送Ajax请求
请求报文【请求行,请求头,空行,请求体】
请求行:由方法字段、URL 字段 和HTTP 协议版本字段 3 个部分组成,他们之间使用空格隔开。
请求头:由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息。
空行:最后一个响应头部之后是一个空行,发送回车符和换行符,通知服务器以下不再有响应头部。
请求体:请求体不在 GET 方法中使用,而是在POST 方法中使用。POST 方法适用于需要客户填写表单的场合。与请求包体相关的最常使用的是包体类型 Content-Type 和包体长度 Content-Length;
报文结构复杂,不可能手写。好在浏览器为我们提供了一个XMLHttpRequest对象。XMLHttpRequest对象是AJAX中非常重要的对象,所有的AJAX操作都是基于该对象的。
XMLHttpRequest获取方式
方式一:var xhr = new XMLHttpRequest():目前主流浏览器都支持
方式二:var xhr = new ActiveXObject("Msxml2.XMLHTTP"):IE6支持的方式
方式三:var xhr = new ActiveXObject("Microsoft.XMLHTTP"):IE5.5以下支持的方式
通用方法:
//获取XMLHttpRequest的通用方法
function getXMLHttpRequest(){
var xhr;
try{
//大部分浏览器都支持
xhr = new XMLHttpRequest();
}catch(e){
try{
//如果不支持,在这里捕获异常并且采用IE6支持的方式
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
//如果还不支持,在这里捕获异常并采用IE5支持的方式
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xhr;
}
XMLHttpRequest方法
-
open(method,url,async):用于设置请求的基本信息,接收三个参数。
-
参数一:method
接收一个字符串,表明请求的方法:get或post
-
参数二:url
请求的地址,接收一个字符串
-
参数三:Assync
发送的请求是否为异步请求,接收一个布尔值。① true 是异步请求 ② false 不是异步请求(同步请求)
-
-
**send(string):**用于将请求发送给服务器,可以接收一个参数
-
string参数
该参数只在发送post请求时需要。用于设置请求体
-
-
setRequestHeader(header,value):用于设置请求头
-
参数一:header参数
字符串类型,要设置的请求头的名字
-
参数二:value参数
字符串类型,要设置的请求头的值
-
XMLHttpRequest对象的属性:
-
readyState
- 描述XMLHttpRequest的状态
- 一共有五种状态分别对应了五个数字:
- 0 :请求尚未初始化,open()尚未被调用
- 1 :服务器连接已建立,send()尚未被调用
- 2 :请求已接收,服务器尚未响应
- 3 :请求已处理,正在接收服务器发送的响应
- 4 :请求已处理完毕,且响应已就绪。
-
status
-
请求的响应码
-
200 响应成功
-
404 页面为找到
-
500 服务器内部错误
… … … …
-
-
-
onreadystatechange
- 该属性需要指向一个函数
- 该函数会在readyState属性发生改变时被调用
-
responseText
- 获得字符串形式的响应数据。
-
responseXML(用的比较少)
- 获得 XML 形式的响应数据。
JQuery发送Ajax请求
<script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>
<script>
//ajax基本语法
$.ajax({
url:"${pageContext.request.contextPath}/TestAjaxServlet", //请求路径
type:"POST", //请求方式【GET|POST|PUT|DELETE】
// data:"stuName=yanfei&stuAge=18", //请求参数
data:{"stuName":"chengbo","stuAge":18}, //请求json参数
dataType:"json", //服务器预期返回数据类型[text|json|jsonp]
success:function(rs){ //回调函数【请求成功】
alert("rs:"+rs.stuAge);
},
error:function(){ //回调函数【请求失败】
alert("请求失败!");
}
});
//ajax简写语法
//$.get(url,[data],[success:fn],[dataType]):以GET请求方式,发送请求
//$.post(url,[data],[success:fn],[dataType]):以POST请求方式,发送请求
//$.getJSON(url,[data],[success:fn]):以GET请求方式,发送请求;并以json格式响应数据【dataType=json】
</script>
Vue发送Ajax请求
Axios
JSON
简介
JSON全称:JavaScript Object Notation【JS提供的一种轻量级的数据交换格式】
本质:JavaScript对象,与字符串可以进行转换
作用:JSON可以在不同语言,不同生态之间进行数据交互
使用
语法:
//定义json对象
var jsons = {
"key1":"abc", // 字符串类型
"key2":1234, // Number
"key3":[1234,"21341","53"], // 数组
"key4":{ // json类型
"key4_1" : 12,
"key4_2" : "kkk"
},
"key5":[{ // json数组
"key5_1_1" : 12,
"key5_1_2" : "abc"
},
{
"key5_2_1" : 41,
"key5_2_2" : "bbj"
}]
};
//abc
// alert(jsons.key1);
//53
// alert(jsons.key3[2]);
//kkk
// alert(jsons.key4.key4_2);
//bbj
alert(jsons.key5[1].key5_2_2);
类型转换
在Js语言环境下,Json对象与Json字符串转换问题
- Json对象->Json字符串
- var jsonString = JSON.stringify(JsonObj);
- Json字符串->Json对象
- var jsonObj = JSON.parse(jsonString);
在Java语言环境下,Java对象【JavaBean&List&Map】与Json字符串转换问题
使用Google下Gson工具
-
Java对象->Json字符串
- Gson gson = new Gson(); //使用toJson()方法,将javaBean转换为Json字符串 String jsonString = gson.toJson(student);//参数是对象
- Gson gson = new Gson(); String s = gson.toJson(list); //参数是对象的可变数组
-
Json字符串->Java对象【JavaBean&List&Map】
Student student1 = gson.fromJson(jsonString, Student.class);//单个JSON对象字符串转换List<Student> list1 = gson.fromJson(s, new TypeToken<List<Student>>() { }.getType());//多个JSON对象字符串转换
代码
@Test
public void testJavaBeanAndJsonString(){
//将JavaBean->JsonString
Student student = new Student(1001,"yanfei",18);
Gson gson = new Gson();
//使用toJson()方法,将javaBean转换为Json字符串
String jsonString = gson.toJson(student); //String str = "{\"id\":1001,\"stuName\":\"yanfei\"}";
System.out.println("jsonString = " + jsonString);
//将JsonString->JavaBean
Student student1 = gson.fromJson(jsonString, Student.class);
System.out.println("student1 = " + student1.getStuName());
}
@Test
public void testListAndJsonString(){
//List<Student> -> jsonString
List<Student> list = new ArrayList<>();
list.add(new Student(1001,"yanfei",18));
list.add(new Student(1002,"ligen",19));
list.add(new Student(1003,"chengbo",38));
Gson gson = new Gson();
String s = gson.toJson(list); //[{"":""},{"":""},{"":""}] 或{{"":""},{"":""},{"":""}}
System.out.println("s = " + s);
//jsonString -> List<Student>
List<Student> list1 = gson.fromJson(s, new TypeToken<List<Student>>() {
}.getType());
for (Student student : list1) {
System.out.println("student = " + student.getStuName());
}
}
@Test
public void testMapAndJsonString(){
Map<String,Student> map = new HashMap<>();
map.put("yanfei",new Student(1001,"yanfei",18));
map.put("ligen",new Student(1002,"ligen",19));
map.put("chengbo",new Student(1003,"chengbo",38));
//将map->jsonString
Gson gson = new Gson();
String s = gson.toJson(map);
System.out.println("s = " + s);
//jsonString->Map<String,Student>
Map<String,Student> map1 = gson.fromJson(s, new TypeToken<Map<String, Student>>() {
}.getType());
System.out.println(map1.get("chengbo").getStuAge());
}
Axios
简介
使用原生的JavaScript程序执行Ajax极其繁琐,所以一定要使用框架来完成。而Axios就是目前最流行的前端Ajax框架。
Axios官网:www.axios-js.com/
基本用法
引入方式和Vue一样,导入对应的*.js文件即可。
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
我们可以把这个axios.min.js文件下载下来保存到本地来使用。
在前端页面引入开发环境
<script type="text/javascript" src="/demo/static/vue.js"></script>
<script type="text/javascript" src="/demo/static/axios.min.js"></script>
需要先引入Vue。
发送普通请求参数
1 html
<div id="app">
<button @click="commonParam">普通请求参数</button>
</div>
2 Vue+axios代码:
var vue = new Vue({
"el":"#app",
"data":{
"message":""
},
"methods":{
commonParam(){
//使用axios发送异步请求
axios({
"method":"post",
"url":"demo01",
"params":{
"userName":"tom",
"userPwd":"123456"
}
}).then(response => {
//then里面是处理请求成功的响应数据
//response就是服务器端的响应数据,是json类型的
//response里面的data就是响应体的数据
this.message = response.data
}).catch(error => {
//error是请求失败的错误描述
//error.response就是请求失败时候的响应信息
console.log(error.response)
})
}
}
})
</script>
效果:所有请求参数都被放到URL地址后面了,哪怕我们现在用的是POST请求方式。
3 后端代码
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Chunsheng Zhang
* 日期2021-05-21 09:15
*/
public class ServletDemo01 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//1. 接收请求参数userName和userPwd
String userName = request.getParameter("userName");
String userPwd = request.getParameter("userPwd");
System.out.println(userName + ":" + userPwd);
//模拟出现异常
//int num = 10/0;
//2. 向浏览器响应数据
response.getWriter().write("hello world!!!");
}
}
4 axios程序接收的响应对象结构
| 属性名 | 作用 |
|---|---|
| config | 调用axios(config对象)方法时传入的JSON对象 |
| data | 服务器端返回的响应体数据 |
| headers | 响应消息头 |
| request | 原生JavaScript执行Ajax操作时使用的XMLHttpRequest |
| status | 响应状态码 |
| statusText | 响应状态码的说明文本 |
5 服务器端处理请求失败后
catch(error => { // catch()服务器端处理请求出错后,会调用
console.log(error); // error就是出错时服务器端返回的响应数据
console.log(error.response); // 在服务器端处理请求失败后,获取axios封装的JSON格式的响应数据对象
console.log(error.response.status); // 在服务器端处理请求失败后,获取响应状态码
console.log(error.response.statusText); // 在服务器端处理请求失败后,获取响应状态说明文本
console.log(error.response.data); // 在服务器端处理请求失败后,获取响应体数据
});
在给catch()函数传入的回调函数中,error对象封装了服务器端处理请求失败后相应的错误信息。其中,axios封装的响应数据对象,是error对象的response属性。response对象的结构还是和then()函数传入的回调函数中的response是一样的。
什么是回调函数?
开发人员声明,但是调用时交给系统来调用。像单击响应函数、then()、catch()里面传入的都是回调函数。回调函数是相对于普通函数来说的,普通函数就是开发人员自己声明,自己调用:
function sum(a, b) { return a+b; } var result = sum(3, 2); console.log("result="+result);
发送JSON请求体
1 html
<button @click="sendJsonBody">请求体JSON</button>
2 Vue+axios代码:
<script>
var vue = new Vue({
"el":"#app",
"data":{
"message":""
},
"methods":{
sendJsonBody(){
axios({
"method":"post",
"url":"demo02",
"data":{
"username":"奥巴马",
"password":"123456",
"id":1,
"nickname":"圣枪游侠"
}
}).then(response => {
console.log(response.data)
})
}
}
})
</script>
3 后端代码
(1)加入Gson包
GSON是JSON数据解析和生成工具,它可以帮助我们将数据在JSON字符串和Java对象之间互相转换。
(2)User类
package com.atguigu.user;
/**
* 包名:com.atguigu.user
*
* @author Chunsheng Zhang
* 日期2021-05-21 10:18
*/
public class User {
private Integer id;
private String username;
private String password;
private String nickname;
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
public User(Integer id, String username, String password, String nickname) {
this.id = id;
this.username = username;
this.password = password;
this.nickname = nickname;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
(3)servlet
package com.atguigu.servlet;
import com.atguigu.user.User;
import com.atguigu.utils.JsonUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Chunsheng Zhang
* 日期2021-05-21 10:06
*/
public class ServletDemo02 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 1.由于请求体数据有可能很大,所以Servlet标准在设计API的时候要求我们通过输入流来读取
BufferedReader reader = request.getReader();
// 2.创建StringBuilder对象来累加存储从请求体中读取到的每一行
StringBuilder builder = new StringBuilder();
// 3.声明临时变量
String bufferStr = null;
// 4.循环读取
while((bufferStr = reader.readLine()) != null) {
builder.append(bufferStr);
}
// 5.关闭流
reader.close();
// 6.累加的结果就是整个请求体
String requestBody = builder.toString();
// 7.创建Gson对象用于解析JSON字符串
Gson gson = new Gson();
// 8.将JSON字符串还原为Java对象
User user = gson.fromJson(requestBody, User.class);
System.out.println("user = " + user);
System.out.println("requestBody = " + requestBody);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("hello world");
}
}
此处可简化代码,在SpringMVC中提供@RequestBody,可以用来简化代码
服务器端返回JSON数据
1 前端
sendJsonBody(){
axios({
"method":"post",
"url":"demo03"
}).then(response => {
console.log(response.data.nickname)
})
}
2 后端
(1)加入Gson包
(2)Servlet代码
package com.atguigu.servlet;
import com.atguigu.user.User;
import com.atguigu.utils.JsonUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Chunsheng Zhang
* 日期2021-05-21 10:06
*/
public class ServletDemo03 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//1. 创建user对象设置数据
User user = new User(1,"aobama","123456","圣枪游侠");
//2. 创建Gson对象用于将user对象转成json字符串
Gson gson = new Gson();
//3. 将user对象转成json字符串
String jsonStr = gson.toJson(user);
response.getWriter().write(jsonStr);
}
}