Ajax
一.Ajax概述
1.应用场景
在线视频、直播平台等...评论实时更新、点赞、小礼物、...
会员注册时的信息验证,手机号、账号唯一
百度关键搜索补全功能
2.简介
Ajax 即"Asynchronous Javascript And XML"(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术
Ajax 是一种用于创建快速动态网页的技术
Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面
3.特点
4.异步与同步方式区别
(1)同步方式发送请求
发送一个请求,需要等待响应返回,然后才能够发送下一个请求,如果该请求没有响应,不能发送下一个请求,客户端会处于一直等待过程中
(2)异步方式发送请求
发送一个请求,不需要等待响应返回,随时可以再发送下一个请求,即不需要等待
二.JS原生方式实现异步
1.实现步骤
jsp
复制代码
1、创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
2、使用open方法指定请求的相关信息
xhr.open("get/post","***Servlet",true);
3、使用send方法发送请求
xhr.send();
4、定义onreadystatechange的函数
xhr.onreadystatechange = function(){}
5、当readystate属性值为4时
xhr.readyState == 4;
6、获取响应信息
var msg = xhr.responseText;
7、处理信息
2.案例
(1)video.jsp
jsp
复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script>
function like() {
var xhr = new XMLHttpRequest();
xhr.open("get","likeServlet",true);
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {
var msg = xhr.responseText;
document.getElementById("num").innerText = msg;
}
}
}
</script>
</head>
<body>
<video src="test.mp4" controls width="500"></video><br>
<input type="button" value="点赞" οnclick="like()">
当前点赞量:<span style="color: red;" id="num">${empty applicationScope.count ? 0 : applicationScope.count}</span>
</body>
</html>
(2)likeServlet.java
java
复制代码
package com.lfg.servlet;
import javax.servlet.ServletContext;
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.io.PrintWriter;
@WebServlet("/likeServlet")
public class LikeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取原本的点赞量+1,将新的点赞量放回去
ServletContext servletContext = getServletContext();
Integer count = (Integer) servletContext.getAttribute("count");
//如果当前点赞是第一个点赞
if (count == null) {
count = 1;
} else {
count++;
}
servletContext.setAttribute("count",count);
//将最新的点赞量还给Ajax
PrintWriter out = resp.getWriter();
out.print(count);
out.close();
}
}
三.jQuery方式实现异步
1.概述
jQuery是一个优秀的js框架,自然对JS原生的Ajax进行了封装,封装后的Ajax的操作方法更简洁,功能更强大,这也是程序员最普遍使用,语法结构简单,代码可读性好。
2.Ajax操作相关的jQuery方法
请求方式
语法
Ajax请求
$.ajax([settings])
GET请求
$.get(url, [data] , [callback] , [type] )
POST请求
$.post(url, [data] , [callback] , [type] )
(1)Ajax请求
a.语法
Javascript
复制代码
$.ajax({
url:"",
data:{},
type:"post/get",
async:true,
dataType:"text",
success:function(obj){
},
error:function(){
}
})
b.属性解析
参数名称
描述
url
请求的服务器端url地址, 与form表单中的action一样,都是代表请求的路径
data
前台需要向后台传递的数据(键值对形式)
type
和form表单中method对应,代表请求类型 get/post
async
取值是布尔类型true/false,分别表示异步和同步,默认为true(异步),一般不建议写
dataType
回传的数据类型。text、xml、html、json...
success
成功的回调函数,参数obj表示返回值
error
失败的回调函数,一般不写
c.注意事项
每个属性后都要跟随一个英文逗号,最后一个不用。
每一个属性都是键值对的形式存在,中间用英文冒号:隔开
data:{} 是一个特殊的写法,值是一个{},里面使用键值对存储
例如:data:{"键1":值1, "键2":值2, "键3":值3}
引入jQuery
d.示例
javascript
复制代码
$(function () {
$("#btn").click(function () {
$.ajax({
url:"likeServlet",
data:null,
type:"get",
async:true,
dataType:"text",
success:function (obj) {
$("#num").text(obj);
},
error:function () {
alert("测试");
}
});
});
});
(2)GET请求
a.语法格式
javascript
复制代码
$.get(url, [data], [callback], [type]);
b.属性解析
参数名称
描述
url
请求的服务器端url地址, 与form表单中的action一样,都是代表请求的路径
data
前台需要向后台传递的数据(键值对形式)
callback
当请求成功后的回掉函数,可以在函数体中编写我们的逻辑代码
type
预期的返回数据的类型,取值可以是 text、xml、html、json...
c.注意事项
写法功能和$.ajax是一样的,但是严格要求属性顺序。
引入jQuery
d.示例
Javascript
复制代码
$.get("likeServlet",null,function (obj) {
$("#num").text(obj);
},"text");
(3)POST请求
a.语法
javascript
复制代码
$.post(url, [data], [callback], [type]);
b.属性解析
参数名称
描述
url
请求的服务器端url地址, 与form表单中的action一样,都是代表请求的路径
data
前台需要向后台传递的数据(键值对形式)
callback
当请求成功后的回掉函数,可以在函数体中编写我们的逻辑代码
type
预期的返回数据的类型,取值可以是 text、xml、html、json...
c.注意事项
写法功能和$.ajax是一样的,但是严格要求属性顺序
引入jQuery
d.示例
javascript
复制代码
$.post("likeServlet",null,function (obj) {
$("#num").text(obj);
},"text");
(4) . a j a x 与 .ajax与 .ajax与.get|$.post异同
相同点
不同点
都是jQuery封装的方法实现异步交互
$.ajax()是jQuery的第一次封装,使用时稍显麻烦,但是功能强大,覆盖了get和post请求,有错误调试能力,写法顺序可以改变。
. p o s t ( ) 和 .post()和 .post()和.get()是jQuery Ajax的第二次封装,由于 . A j a x ( ) 写法过于臃肿,简化为 .Ajax()写法过于臃肿,简化为 .Ajax()写法过于臃肿,简化为.post()和$.get(),功能是相同的没有区别。但是写法要求更高,顺序不能改变。
3.案例
(1)需求
在用户注册页面,输入用户名,当用户名输入框失去焦点时,发送异步请求,将输入框的用户名传递给服务器端进行是否存在的校验。
(2)register.jsp
jsp
复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
<script src="jquery-3.6.4.js"></script>
<script>
$(function () {
// blur()失焦事件
$("[name=username]").blur(function () {
//获取用户输入的账号
var username = $(this).val();
//携带数据发送Ajax请求
$.post("registerServlet",{"name":username},function(obj){
if (obj) {
$("#username_msg").text("√");
} else {
$("#username_msg").text("该账号已存在");
}
},"json");
});
});
</script>
</head>
<body>
<form action="" method="">
账号:<input type="text" name="username"><span id="username_msg"></span><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
(3)RegisterServlet.java
java
复制代码
package com.lfg.servlet;
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.io.PrintWriter;
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String name = req.getParameter("name");
boolean res = true;
//账号不能是admin和chenwei
if ("admin".equals(name) || "lfg".equals(name)) {
res = false;
}
PrintWriter out = resp.getWriter();
out.print(res);
out.close();
}
}
(4)返回效果
四.Ajax返回值类型介绍
类型
介绍
XML
太麻烦,解析太费劲,已经不使用
HTML
网页,其实质和返回文本一样,没区别,一般使用文本代替
script
直接返回脚本
Text(文本)
(默认返回类型)字符串类型,返回直接接收字符串
json
返回是一个json对象,脚本中可以直接操作这个对象,非常方便
jsonp
和Json一样,只不过这个支持跨域访问
五.JSON数据格式
1.JSON概述
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。
它基于ECMAScript的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
JSON本质上就是格式有点特殊的字符串。
2.JSON语法格式
类型
语法
解释
对象类型
{name:value,name:value...}
其中name是字符串类型,而value是任意类型
数组类型
[value,value,value...]
其中value是任意类型
混合类型
[{},{}... ...] 或 {name:[]... ...}
合理包裹嵌套对象类型和数组类型
3.JSON书写规范
使用{}和[]书写,{}表示对象类型,[]表示数组类型
对象类型中每组数据之间用逗号隔开,每组中的关键字与值之间用冒号隔开
数组类型中每个值之间用逗号隔开,最后一个值后面不要加逗号
4.JSON数据应用
(1)概述
json的转换工具是通过java封装好的一些jar工具包,直接将java对象或集合转换成json格式的字符串。
json可以直接接收boolean值,故不用转字符串
(2)JSON数据中转换常用工具
工具名称
介绍
Jsonlib
Java 类库,需要导入的jar包较多
Gson
google提供的一个简单的json转换工具
Fastjson
alibaba技术团队提供的一个高性能的json转换工具
Jackson
开源免费的json转换工具,springmvc转换默认使用jackson
5.JSON使用步骤
(1)导入json相关jar包
jackson-annotations-2.7.9.jar
jackson-core-2.7.9.jar
jackson-databind-2.7.9.jar
(2)创建java对象或集合
jsp
复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="jquery-3.6.4.js"></script>
<script>
$(function () {
$("#btn").click(function () {
$.get("jsonServlet",null,function (obj) {
console.log(obj);
//解析对象
//console.log(obj.sid+","+obj.name);
//解析数组
/*for (var i = 0;i < obj.length;i ++) {
console.log(obj[i]);
}*/
//解析装满学生对象的数组
/*for (var i = 0;i < obj.length;i ++) {
console.log(obj[i].sid+","+obj[i].name);
}*/
//解析map
var students = obj.students;
for (var i = 0;i < students.length;i ++) {
console.log(students[i].sid+","+students[i].name);
}
},"json");
});
});
</script>
</head>
<body>
<input type="button" value="测试" id="btn">
</body>
</html>
(3)进行转换
使用jackson的ObjectMapper对象的writeValueAsString方法进行转换
JsonServlet.java
java
复制代码
package com.lfg.servlet;
import com.lfg.entity.Student;
import com.fasterxml.jackson.databind.ObjectMapper;
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.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet("/jsonServlet")
public class JsonServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//对象类型
Student student = new Student(1,"mary");
//数组类型
String[] strs = {"abc","bcd","cde"};
//混合类型(集合)
List<Student> list = new ArrayList<>();
Student student1 = new Student(1,"mary");
Student student2 = new Student(2,"tom");
Student student3 = new Student(3,"jack");
list.add(student1);
list.add(student2);
list.add(student3);
Map<String,Object> map = new HashMap<>();
map.put("students",list);
//使用Jackson进行数据类型转换
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(map);
System.out.println(str);
PrintWriter out = resp.getWriter();
out.print(str);
out.close();
}
}
6.案例
(1)需求
在输入框输入关键字,下拉框中异步显示与该关键字相关的学生姓名
(2)search.jsp
jsp
复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>百度一下</title>
<style type="text/css">
* {
margin: 0px;
padding: 0px;
}
#box {
display: inline-block;
}
#search {
width: 545px;
height: 42px;
border-color: #4E6EF2;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
float: left;
}
#btn {
width: 108px;
height: 42px;
background-color: #4e6ef2;
color: #fff;
border: none;
font-size: 17px;
font-weight: 400;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
float: left;
}
#show {
width: 545px;
border: 1px solid #4e6ef2;
position: relative;
left: -55px;
text-align: left;
}
</style>
<script src="jquery-3.6.4.js"></script>
<script>
$(function () {
$("#search").bind("input propertyChange",function () {
//获取输入的数据
var sname = $(this).val();
if (sname != "") {
$.get("studentServlet",{"sname":sname},function (obj) {
var div = "";
for (var i = 0;i < obj.length;i ++) {
div += "<div>"+obj[i].sname+"</div>";
}
$("#show").html(div);
},"json");
} else {
$("#show").html("");
}
});
});
</script>
</head>
<body>
<center>
<img alt="" width="310" height="150" src="http://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"><br/>
<div id="box">
<input id="search" type="text" name="search"/>
<button id="btn">百度一下</button>
</div>
<div id="show">
</div>
</center>
</body>
</html>
(3)StudentServlet.java
java
复制代码
package com.lfg.servlet;
import com.lfg.entity.Student;
import com.lfg.service.StudentService;
import com.lfg.service.impl.StudentServiceImpl;
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.io.PrintWriter;
import java.util.List;
@WebServlet("/studentServlet")
public class StudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
String sname = req.getParameter("sname");
StudentService studentService = new StudentServiceImpl();
String res = studentService.getStudentBySname(sname);
PrintWriter out = resp.getWriter();
out.print(res);
out.close();
}
}
(4)Service
java
复制代码
package com.lfg.service;
public interface StudentService {
String getStudentBySname(String sname);
}
package com.lfg.service.impl;
import com.lfg.dao.StudentDao;
import com.lfg.dao.impl.StudentDaoImpl;
import com.lfg.entity.Student;
import com.lfg.service.StudentService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class StudentServiceImpl implements StudentService {
StudentDao studentDao = new StudentDaoImpl();
@Override
public String getStudentBySname(String sname) {
List<Student> list = studentDao.getStudentBySname(sname);
ObjectMapper mapper = new ObjectMapper();
String str = "";
try {
str = mapper.writeValueAsString(list);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return str;
}
}
(5)Dao
java
复制代码
package com.lfg.dao;
import com.lfg.entity.Student;
import java.util.List;
public interface StudentDao {
List<Student> getStudentBySname(String sname);
}
package com.etime.dao.impl;
import com.etime.dao.StudentDao;
import com.etime.entity.Student;
import com.etime.util.C3P0Util;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
public class StudentDaoImpl implements StudentDao {
QueryRunner queryRunner = new QueryRunner(C3P0Util.getDataSource());
@Override
public List<Student> getStudentBySname(String sname) {
List<Student> list = null;
String sql = "select * from student where sname like ?";
try {
list = queryRunner.query(sql, new BeanListHandler<>(Student.class),"%"+sname+"%");
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
(6)实现效果
六.同异步
1.jsp
jsp
复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="jquery-3.6.4.js"></script>
<script>
$(function () {
$("#btn").click(function () {
$.ajax({
url:"asyncServlet",
data:{"flag":"first"},
type:"get",
dataType:"text",
async:false,
success:function (obj) {
$("body").append(obj);
}
});
$.ajax({
url:"asyncServlet",
data:{"flag":"second"},
type:"get",
dataType:"text",
async:false,
success:function (obj) {
$("body").append(obj);
}
});
});
});
</script>
</head>
<body>
<input type="button" value="同异步测试" id="btn">
</body>
</html>
2.servlet
java
复制代码
package com.lfg.servlet;
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.io.PrintWriter;
@WebServlet("/asyncServlet")
public class AsyncServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String flag = req.getParameter("flag");
PrintWriter out = resp.getWriter();
if ("first".equals(flag)) {
out.print("<div style='background-color:red;'>" + flag + "</div>");
} else {
out.print("<div style='background-color:green;'>" + flag + "</div>");
}
out.close();
}
}
3.注意事项
必须使用同步的情况:第二个请求需要的数据是第一个请求返回的结果时
设置同步请求