异步请求 AJAX
本文章基于B站UP主:楠哥教你学Java 的课程《Java Web从入门到实战【完整版】》进行整理补充,本文章仅用于个人学习交流使用。
1.基本使用
Asynchronous JavaScript And XML:异步的 JavaScript 和 XML
AJAX 不是新的编程,指的是⼀种交互⽅式,异步加载,客户端和服务器的数据交互更新在局部⻚⾯的技术,不需要刷新整个⻚⾯(局部刷新)
同步加载:如果请求分两步完成,当写完第一部分时,进入第二部分会刷新页面,第一部分的内容会被刷新,无法保留
异步请求优点:
1、局部刷新,效率更⾼
2、⽤户体验更好
3、操作之间互不影响
基于 jQuery 的 AJAX
引入JQuery:在web目录下面新建js 文件夹,将 jquery-3.4.1.min.js粘贴进去
在 .jsp 文件 <head>中写入:<script type=“text/javascript” src=“js/jquery-3.4.1.min.js”></script>
2.传统的 WEB 数据交互 和 AJAX 数据交互
- 客户端请求的⽅式不同:
传统:浏览器发送同步请求 (form、 a)
AJAX:异步引擎对象发送异步请求
- 服务器响应的⽅式不同:
传统:响应⼀个完整 JSP ⻚⾯(视图)
AJAX:响应需要的数据
- 客户端处理⽅式不同:
传统:需要等待服务器完成响应并且重新加载整个⻚⾯之后,⽤户才能进⾏后续的操作
AJAX:动态更新⻚⾯中的局部内容,不影响⽤户的其他操作
3.AJAX原理
4.基于 jQuery 的 AJAX 语法
$.ajax({属性})
常⽤的属性参数:
url:请求的后端服务地址
type:请求⽅式,默认 get
data:请求参数
dataType:服务器返回的数据类型, text/json
success:请求成功的回调函数
error:请求失败的回调函数
complete:请求完成的回调函数(⽆论成功或者失败,都会调⽤)
5.响应文本
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$(function () {
var btn=$("#btn");
btn.click(function () {
//将数据请求到后台
$.ajax({
<!--url相当于action-->
url:'/test',
type:'post',
data:'id=1',<!--?id=1-->
dataType:'text',<!--服务器返回的类型,返回文本text,返回对象JSON-->
success:function (data) {
<!--服务器成功响应之后调用此方法,传数据到data-->
var text=$("#text");
text.before("<span>"+data+"</span><br/>")
}
})
});
})
</script>
</head>
<body>
${str}
<!--不能通过表单提交,为按钮添加事件-->
<input type="text" id="text"> <br>
<input type="button" value="提交" id="btn">
</body>
</html>
TestServlet.java
package com.lut.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;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String id=req.getParameter("id");
String str="hello";
resp.getWriter().write(str);
//req.setAttribute("str",str);
// req.getRequestDispatcher("test.jsp").forward(req,resp);
}
}
注意:
不能⽤表单提交请求,改⽤ jQuery ⽅式动态绑定事件来提交。
Servlet 不能跳转到 JSP(这样返回的是整个jsp代码),只能将数据返回。
功能展示:
主界面:
![](https://i-blog.csdnimg.cn/blog_migrate/6324a6fdee9a5f4c66dfd4e116c69fac.png)
当点击提交按钮时,文本框上面会出现一行文字,且此时文本框里面的内容不受影响。
![](https://i-blog.csdnimg.cn/blog_migrate/8d32ac1978358fe8b8b623a1edcc1796.png)
6.响应对象
JavaScript Object Notation,⼀种轻量级数据交互格式,完成 js 与 Java 等后端开发语⾔对象数据之间的转换
客户端和服务器之间传递对象数据,需要⽤ JSON 格式。
Java中的对象
User user=new User(1,"张三",96.6);
Jsp中的对象
var user={
id:1,
name:张三,
score:96.5
}
Jsp无法直接获取 Java对象,需要将 Java 对象转换为 Jsp ,为此需要引入Jar包并进行配置。
引入jar包,一共有6个:
![](https://i-blog.csdnimg.cn/blog_migrate/61c41cd2110526ded018b73f795a53dd.png)
对象类:User.java
package com.lut.entity;
public class User {
private Integer id;
private String name;
private Double score;
public User(Integer id, String name, Double score) {
this.id = id;
this.name = name;
this.score = score;
}
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;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
}
服务类:TestServlet.java
package com.lut.servlet;
import com.lut.entity.User;
import net.sf.json.JSONObject;
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("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user=new User(1,"张三",96.6);
//将 Java 对象转为 JSON 对象
resp.setCharacterEncoding("utf-8");//处理乱码
JSONObject jsonObject=JSONObject.fromObject(user);
resp.getWriter().write(jsonObject.toString());
}
}
页面:test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$(function () {
var btn=$("#btn");
btn.click(function () {
//将数据请求到后台
$.ajax({
<!--url相当于action-->
url:'/test',
type:'post',
data:'id=1',<!--?id=1-->
dataType:'json',<!--服务器返回的类型.返回对象JSON-->
success:function (data) {
$("#id").val(data.id);
$("#name").val(data.name);
$("#score").val(data.score);
}
})
});
})
</script>
</head>
<body>
编号:<input id="id" type="text"><br>
姓名:<input id="name" type="text"><br>
成绩:<input id="score" type="text"><br>
<input type="button" value="提交" id="btn">
</body>
</html>
功能展示:
界面:
![](https://i-blog.csdnimg.cn/blog_migrate/92d333988b3feca41a8158de6aceee86.png)
当点击提交按钮时,会获取对象的值并输出
![](https://i-blog.csdnimg.cn/blog_migrate/695e9981565e39cd3d7c9e55be912416.png)
7.使用场景
1.进行信息注册时,提示 用户名是否可用,重复密码是否正确等
2.进行多级菜单的联动,例如 省份,城市,区 的选择
这里用数据库处理信息比较容易一些,这里主要侧重点是 省/市/区 的响应
Location.java
package com.lut.entity;
import java.util.List;
public class Location {
private List<String> cities;
private List<String> areas;
public List<String> getCities() {
return cities;
}
public void setCities(List<String> cities) {
this.cities = cities;
}
public List<String> getAreas() {
return areas;
}
public void setAreas(List<String> areas) {
this.areas = areas;
}
}
LocationServlet.java
package com.lut.servlet;
import com.lut.entity.Location;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
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;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet("/location")
public class LocationServlet extends HttpServlet {
private static Map<String, List<String>> cityMap;
private static Map<String,List<String>> provinceMap;
static {
cityMap = new HashMap<>();
List<String> areas = new ArrayList<>();
//⻄安
areas.add("雁塔区");
areas.add("莲湖区");
areas.add("新城区");
cityMap.put("⻄安市",areas);
//宝鸡
areas = new ArrayList<>();
areas.add("陈仓区");
areas.add("渭宾区");
areas.add("新城区");
cityMap.put("宝鸡市",areas);
//渭南
areas = new ArrayList<>();
areas.add("临渭区");
areas.add("⾼新区");
cityMap.put("渭南市",areas);
//郑州
areas = new ArrayList<>();
areas.add("郑州A区");
areas.add("郑州B区");
cityMap.put("郑州市",areas);
//洛阳
areas = new ArrayList<>();
areas.add("洛阳A区");
areas.add("洛阳B区");
cityMap.put("洛阳市",areas);
provinceMap = new HashMap<>();
List<String> cities = new ArrayList<>();
cities.add("⻄安市");
cities.add("宝鸡市");
cities.add("渭南市");
provinceMap.put("陕⻄省",cities);
cities = new ArrayList<>();
cities.add("郑州市");
cities.add("洛阳市");
cities.add("开封市");
provinceMap.put("河南省",cities);
cities = new ArrayList<>();
cities.add("南京市");
cities.add("苏州市");
cities.add("南通市");
provinceMap.put("江苏省",cities);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String type = req.getParameter("type");
resp.setCharacterEncoding("UTF-8");
String id = req.getParameter("id");
switch (type){
case "city":
List<String> areas = cityMap.get(id);
JSONArray jsonArray = JSONArray.fromObject(areas);
resp.getWriter().write(jsonArray.toString());
break;
case "province":
List<String> cities = provinceMap.get(id);
String city = cities.get(0);
List<String> cityAreas = cityMap.get(city);
Location location = new Location();
location.setCities(cities);
location.setAreas(cityAreas);
JSONObject jsonObject = JSONObject.fromObject(location);
resp.getWriter().write(jsonObject.toString());
break;
}
}
}
location.jsp
<%--
Created by IntelliJ IDEA.
User: DELL
Date: 2020/4/4
Time: 17:04
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script>
$(function () {
//修改省份
$("#province").change(function () {
var id = $(this).val();
$.ajax({
url:"/location",
type:"POST",
data:"id="+id+"&type=province",
dataType:"JSON",
success:function(data){
var content = "";
var cities = data.cities;
for(var i=0;i<cities.length;i++){
content += "<option>"+cities[i]+"</option>";
}
$("#city").html(content);
content = "";
var areas = data.areas;
for(var i=0;i<areas.length;i++){
content += "<option>"+areas[i]+"</option>";
}
$("#area").html(content);
}
});
});
//修改城市
$("#city").change(function(){
var id = $(this).val();
$.ajax({
url:"/location",
type:"POST",
data:"id="+id+"&type=city",
dataType:"JSON",
success:function(data){
var content = "";
for(var i=0;i<data.length;i++){
content += "<option>"+data[i]+"</option>";
}
$("#area").html(content);
}
});
});
});
</script>
</head>
<body>
省: <select id="province">
<option value="陕⻄省">陕⻄省</option>
<option value="河南省">河南省</option>
<option value="江苏省">江苏省</option>
</select>
市: <select id="city">
<option value="⻄安市">⻄安市</option>
<option value="宝鸡市">宝鸡市</option>
<option value="渭南市">渭南市</option>
</select>
区: <select id="area">
<option>雁塔区</option>
<option>莲湖区</option>
<option>新城区</option>
</select>
</body>
</html>
页面展示: