目录
1、ajax概述
2、模拟ajax
3、Jquery实现ajax
(1)通用开发步骤
(2)示例 注册用户名重复性验证
(3)示例 ajax解析json数据
(4)实现细节
4、axios实现ajax
5、ajax发送PUT请求引发的“血案”
1、ajax概述
什么是ajax
Ajax:async javascript and XML (异步 JavaScript和XML)
通过在后台与服务器进行少量数据交换,Ajax可以
使网页实现异步更新
。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新
。而传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页面。ajax也是独立于编程语言之外的。
网页同步更新与异步更新的区别
同步提交:当用户发送请求时,当前页面不可以使用,服务器响应页面到客户端,响应完成,用户才可以使用页面。
异步提交:当用户发送请求时,当前页面还可以继续使用,当异步请求的数据响应给页面,页面把数据显示出来 。
在只需要更新局部数据时,如果使用传统的同步更新方式,需要重新加载整个页面的所有资源,造成无意义的资源浪费,也影响用户的体验。
ajax的实现原理
Ajax的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了接口,能够以异步的方式从服务器获取新数据
2、模拟ajax
模拟ajax,分析前端的执行逻辑
编写前端页面
<div>
<p>输入要加载的地址:</p>
<p>
<input type="text" id="url" value="请输入一个网址">
<input type="button" value="提交" onclick="loadPage()">
</p>
</div>
<div>
<h3>
加载页面的位置:
</h3>
<iframe style="width: 100%; height: 430px" id="iframePosition">
</iframe>
</div>
这里做了三部分:
- 输入框,id为"url"
- 一个按钮,绑定点击事件为loadPage()
- 一个iframe区域,id为"iframePosition",用于显示出网页
效果
编写js
<script type="text/javascript">
//创建名为loadPage的函数
function loadPage() {
//获取 id为url 的元素的value属性,即用户输入的URL地址
var targetURL = document.getElementById("url").value;
//设置 id为iframePosition 的元素的src属性 等于 targetURL,就会在iframe中访问该URL对应的网页资源
document.getElementById("iframePosition").src = targetURL;
}
</script>
逻辑:在点击提交按钮时,会调用此函数,通过id获取到输入框元素,再获取到其中的值;通过id获取到iframe元素,设置它的src值等于输入框的value值,就实现了显示用户输入的页面。
用户输入一次网址,点击提交,下方的区域就会显示出目标网页。
此过程中,页面没有刷新,相当于是一个伪异步网站。
3、Jquery实现ajax
(1)通用开发步骤
导入Jquery的js文件
先将Jquery的js文件导入工程,一般存放在src/main/webapp/static/js下
引入Jquery的js文件
<script type="text/javascript" th:src="@{/static/js/jquery-3.6.0.min.js}"></script>
<script type="text/javascript" th:inline="javascript">
编写前端元素
用户名:<input type="text" id="txtName" onblur="checkUser()">
使用到ajax的前端元素
需要具备两个东西
:
- id值
- 事件。当次事件执行后,调用自定义的函数方法,发送ajax请求
编写函数方法
<script type="text/javascript" th:inline="javascript">
function checkUser() {
}
</script>
使用thymeleaf,动态获取到项目的基础路径
<script type="text/javascript" th:inline="javascript">
//动态获取项目根目录
var basePath = [[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]];
function checkUser() {
}
</script>
注意:
- 这个基础目录,目的是动态获取当前项目的基础路径,
与后续指定的请求路径组合成ajax完整的URL路径
- 是固定写法,非常可靠。
编写ajax请求
ajax请求分为三部分:
- url:待访问的路径
- data:待发送的参数
- success:执行成功后执行的回调函数
示例
$.ajax({
//待访问的路径,只有这个是必填的
url: basePath + "/checkUser",
//待发送的参数
data: {'username': $("#txtName").val()},
//载入成功时回调函数
success: function (data) {
//data封装了服务器返回的数据
}
});
除了这样竖着写,也可以精简到一行中:
$.get(basePath + "/checkUser", {'username': $("#txtName").val()}, function (data) {
})
注意:
这种写法只能使用\$.get或\$.post,不能使用\$.ajax,否则无法传递参数!
(2)示例 注册用户名重复性验证
需求
在注册页面,用户填入用户名,用户名输入框失去焦点后,搜索数据库中是否存在该用户名,并展示给用户
后台控制器方法
@RequestMapping("/usernameCheck")
@ResponseBody
public boolean login(String username){
if (null != username){
if ("admin".equals(username)){
//用户名重复,提示用户
return false;
}
}
return true;
}
模拟,如果用户名为admin,提示重复。
前端页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>Ajax 登录验证示例</h3>
用户名:<input type="text" id="inputName" value="请输入用户名" onblur="login()">
<span id="res"></span>
<script type="text/javascript" th:src="@{/static/js/jquery-3.6.0.min.js}"></script>
<script type="text/javascript" th:inline="javascript">
//动态获取项目根目录
var basePath = [[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]];
function login() {
$.post(basePath + "/usernameCheck", {"username":$("#inputName").val()}, function (data) {
if (data) {
//用户名可用;
$("#res").css("color", "green");
$("#res").html("√");
} else {
//用户名不可用
$("#res").css("color", "red");
$("#res").html("用户名已存在!");
}
})
}
</script>
</body>
</html>
(3)示例 ajax解析json数据
需求
前端发出ajax请求,后台返回前端一个User类型的List,前端实现遍历集合并展示
控制器方法
@RequestMapping("/showUser")
@ResponseBody
public List<User> showUser(){
List<User> list = new ArrayList<User>();
list.add(new User("admin1", "123456"));
list.add(new User("admin2", "123456"));
list.add(new User("admin3", "123456"));
list.add(new User("admin4", "123456"));
list.add(new User("admin5", "123456"));
return list;
}
前端页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" id="btn" value="点击发送一个json数据到浏览器">
<table width="80%" align="center">
<tr>
<td>username</td>
<td>password</td>
</tr>
<tbody id="content">
</tbody>
</table>
<script type="text/javascript" th:src="@{/static/js/jquery-3.6.0.min.js}"></script>
<script type="text/javascript" th:inline="javascript">
//动态获取项目根目录
var basePath = [[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]];
$(function () {
$("#btn").click(function () {
$.post(basePath + "/showUser", function (data){
console.log(data);
var html = "";
for (var i=0; i<data.length;i++){
html += "<tr>" +
"<td>" + data[i].username + "</td>" +
"<td>" + data[i].password + "</td>" +
"</tr>"
}
$("#content").html(html);
})
})
})
</script>
</body>
</html>
(4)实现细节
发送ajax请求的流程
某个事件触发函数方法 --> 执行函数该方法 --> 发出ajax请求 --> 访问URL地址,传递数据,接收返回数据
如何处理后台返回的数据
ajax请求中,success对应的回调函数的参数data,即为服务器返回的消息对象,可以是json数据,也可以是基本数据类型。
data可以直接当做普通的对象,用 .属性名 来获取属性值。
如何动态改变前端元素的内容
常与ajax配合的元素是:div、span。
首先,设置元素的id值。然后,在需要赋值的地方,使用Jquery的处理方式
$("#content").html(新内容);
也可以设置该元素的css属性
$("#content").css(新内容);
4、axios实现ajax
Ajax请求可以通过原生方式实现、也可以通过jQuery方式实现,在Vue中,通常使用axios方式(读作阿修斯)
方式实现Ajax。
axios是独立于vue的一个项目,可以用于浏览器和node.js中发送ajax请求。
5、ajax发送PUT请求引发的“血案”
ajax可以直接发送put和delete请求。
但是发送put请求时,SpringMVC不能自动封装pojo类
现象
ajax直接发送put请求,请求体中确实有数据,但SpringMVC无法自动封装pojo类,甚至request.getParameter()都拿不到请求体中的数据!
原因
Tomcat一看是put请求,就不会封装请求体中的数据为map,而只有post形式的请求,才会封装请求体为map。
解决方案
需要发送PUT请求时,不要直接发送,而是发送POST请求,携带"_method=put"的请求参数,由SpringMVC去做处理
。如果要直接发送PUT请求,则必须在web.xml配置HttpPutFormContentFilter过滤器,拦截范围是所有请求
<!-- 对ajax直接发送的PUT请求进行处理-->
<filter>
<filter-name>HttpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpPutFormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
HttpPutFormContentFilter作用:
将请求体中的数据解析、包装成一个map,request被重新包装,request.getParameter()方法被重写,会从重新封装的map中取出数据。