Ajax的使用
本文意在通过小demo来理解如何利用jQuery实现Ajax。
案例1是之前在eclipse上做的还没有使用maven管理。
案例2是后来在idea上做的,使用了maven管理。
案例1——检查员工编号
1. 案例描述:
通过异步处理,检查员工编号是否冲突。点击输入框,如果输入框的内容是1001,则说明编号冲突,则输出编号冲突的提示信息。否则,可以添加此员工编号。
2. 业务需求
在实际信息提交过程中,我们想不是全部提交表单信息后,才能得到后台的处理响应。而是,当输入某一内容后,就立刻对该内容进行判断处理。这时,我们就需要用到Ajax异步处理。
3. 前提准备
lib文件下添加三个Ajax的jar包
js文件夹下添加jQuery的jar包
js文件夹下创建script.js,用来写脚本
将jQuery的jar包和script.js引入Register.jsp文件中
4. 实现逻辑
首先运行Register.jsp
页面,输入框先获取焦点,并输入员工编号。输入框失去焦点后,执行script.js
,将数据异步传送给后台 CheckEmpIdServlet.java
。后台对数据进行处理,若该员工编号存在则返回错误提示信息,若该数据不存在,说明可以添加,就不用返回提示信息了。 如果后台有错误,则在alert中显示状态码。
4.1 Register.jsp
前端登录页面Register.jsp
,输入员工编号,通过jQuery对象向后台进行传递,接受后台传过来的数据进行显示。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-3.2.1.min.js" ></script>
<script src="${pageContext.request.contextPath }/js/script.js"></script>
</head>
<body>
<h1>员工注册</h1>
// 传入员工编号
员工编号:<input type="text" name="empid">
// 显示错误信息
<span style="color:red; font-weight:bold;"></span>
// 隐藏项目路径,发送向后台发送请求时需要该路径
<input type="hidden" id="path" value="${pageContext.request.contextPath }"/>
</body>
</html>
4.2 script.js
通过jQuery调用 ajax方法,向后台传递异步请求。这里对异步请求代码做一个简单的介绍。我们要向后台传递异步数据:
- 我们要明白要向哪里传,需要知道后台地址
url
- 传递数据时的请求方式,
get
还是post
- 是不是异步请求
async
(true or false),这个是默认的,可以不写 - 发送到服务器的数据
data
,数据类型是JSON
对象,没有就不写 - 后台响应的数据类型
dataType
,如果是text
就是字符串,如果是json
就是 JSON对象 - 响应成功后,要执行什么操作
success
。需要已经接受到响应结果readyState=4;并且是正确接收的,状态码status=200。data
参数是后台的响应结果。 - 响应出错后,要执行什么操作
error
。状态码status=400或status=404或500。出错的方法的参数xmlHttpRequest
就是我们传递的请求对象。
// 页面加载后,要执行的功能
$(function(){
// 输入框失去焦点后要执行的功能
$('input[name=empno]').blur(function(){
// 向后台发送异步请求,接受响应结果进行局部判断
$.ajax({
// 访问的后台地址
url:$('#path').val()+"/CheckEmpnoServlet",
//url:${pageContext.request.contextPath}+"/CheckEmpnoServlet",
type:'get',
// 为后台传递的请求参数,以json对象的方式传递,如果不传请求参数,可以省略
data:{empno:$('input[name=empno]').val()},
// 后台响应的数据类型
dataType:'text',
// 响应成功后,要执行的功能
success:function(data){
// 请求对象的readyState等于4并且status等于200是执行该方法
$('span').html(data);
},
// error的function参数就是请求对象XMLHttpRequest
error:function(xmlHttpRequest){
alert(xmlHttpRequest.status);
}
});
});
});
4.3 CheckEmpIdServlet.java
接受前端请求参数,并判断结果。将响应结果返回给前端。
- 接受请求参数,并处理请求参数
- 设置响应的「数据类型」、「编码类型」。如果不设置的话,前台可能无法正常显示。如果数据类型为
text/html
则向前台传递的是字符串;如果数据类型为application/json
则向前台传递的是 JSON对象。编码就设置为utf-8
package com.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class CheckEmpIdServlet
*/
@WebServlet("/CheckEmpIdServlet")
public class CheckEmpIdServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CheckEmpIdServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//response.getWriter().append("Served at: ").append(request.getContextPath());
if(request.getParameter("empid") != null) {
int empId = Integer.parseInt(request.getParameter("empid"));
String msg = "";
if(empId == 1001) {
msg = "该编号已经创建!";
}
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print(msg);
writer.flush();
writer.close();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
5. 运行结果
- 如果输入的员工编号为1001,则输出提示信息
- 如果输入的员工编号不为1001,则说明该编号可以被创建,就不需要任何提示信息
6. 自己遇到的问题
script.js
里的dataType:'text'
写错,alert 提示框输出的readyState=4
,status=200
这里readyState=4
说明接受到了后台的请求数据,status=200
这个说明后台数据是正确的。这里的dataType:'text'
写错是前台的问题。CheckEmpIdServlet.java
里的 response.setContentType(“text/html;charset=utf-8”); 不写或者写错的话,会导致前端页面无法正常显示,像这样:
1. 案例描述
要求页面加载后自动获取到省的全部信息。点击省,获取到对应的市的信息。
2. 环境准备
使用的mvc架构,使用了jstl标签库,EL表达式。
1. 数据库
这里只给出数据库字段:
省:省id、省名称
市:市id、市名称、省id
2. 前端准备
在webapp下的js文件夹下添加jquery包
在webapp下的js文件夹下创建script.js文件,用来写js代码
3. pom.xml
<!--sql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<!--jstl标签库依赖-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--将字符串转化为JSON对象的依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.2.2</version>
</dependency>
4. MVC
省市的 vo层、dao层、service层
3. 前端页面的实现
一个select下拉列表,用来显示省的信息;一个select下拉列表,用来显示市的信息。
3.1 index.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set value="${pageContext.request.contextPath}" var="path"></c:set>
<!DOCTYPE html>
<html>
<head>
<title>JSP - Hello World</title>
<%--引入jquery包和script.js文件--%>
<script src="${path}/js/jquery.js"></script>
<script src="${path}/js/script.js"></script>
</head>
<body>
<%--隐藏当前项目的根目录--%>
<input id="path" type="hidden" value="${path }" />
<label>省:</label>
<select name="provinceId" style="width: 150px"></select>
<label>市:</label>
<select name="cityId" style="width: 150px"></select>
</body>
</html>
4. 获取省信息的实现
页面加载后,向后台发送异步请求,并将获取到的数据在前台进行显示。
4.1 script.js
向SearchProvinceServlet发送请求。用data对象接收后台传过来的数据,并进行处理。
/*为省添加异步请求*/
$(function () {
$.ajax({
url: $('#path').val() + "/SearchProvinceServlet",
type: "get",
dataType: "json",
success: function (data) {
var provinceNode = $('select[name=provinceId]');
provinceNode.empty();
provinceNode.append("<option value='0'>--请选择--</option>");
/*data 是一个JSON数组,对JSON数组进行循环*/
$.each(data, function (i, province) {
var optionNode = '<option value="'+province.provinceId+'">'+province.provinceName+'</option>';
provinceNode.append(optionNode);
});
},
error: function (xmlHttpRequest) {
alert(xmlHttpRequest.status);
}
});
});
4.2 SearchProvinceServlet
获取到省的全部信息,存放在集合中。将集合对象转化为JSON对象,发送给前端。
package servlets;
import com.fasterxml.jackson.databind.ObjectMapper;
import service.ProvinceService;
import vo.Province;
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("/SearchProvinceServlet")
public class SearchProvinceServlet extends HttpServlet {
private ProvinceService provinceService = new ProvinceService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 查询到所有的省的信息
List<Province> provinces = provinceService.selectByProvinceName("");
// 创建ObjectMapper对象,将集合对象转化为JSON字符串
ObjectMapper mapper = new ObjectMapper();
String provinceJson = mapper.writeValueAsString(provinces);
// 设置响应的数据类型,编码方式
response.setContentType("application/json;charset=utf-8");
// 创建writer对象,返回异步信息
PrintWriter writer = response.getWriter();
writer.print(provinceJson);
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
5. 获取市信息的实现
5.1 script.js
向后台发送请求信息,通过省id获取到对应的市的信息,用data接收。通过循环data对象,来显示所有的市的数据。
/*为市添加异步请求*/
$(function () {
$("select[name=provinceId]").change(function () {
$.ajax({
url: $('#path').val() + "/SearchCityServlet",
type: "post",
async:true,
data: {provinceId:$("select[name=provinceId]").val()},
dataType: "json",
success: function (data) {
var cityNode = $("select[name=cityId]");
cityNode.empty();
cityNode.append('<option value="0">--请选择--</option>');
$.each(data, function (i, city) {
var optionNode = "<option value='"+city.cityId+"'>"+city.cityName+"</option>";
cityNode.append(optionNode);
});
},
error: function (xmlHttpRequest) {
alert(xmlHttpRequest.status);
}
});
});
});
5.2 SearchCityServlet
这里我没有使用注解,而是配置了web.xml文件。通过省id获取到对应的市的信息,发送给前端。
package servlets;
import com.fasterxml.jackson.databind.ObjectMapper;
import service.CityService;
import vo.City;
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("/SearchCityServlet")
public class SearchCityServlet extends HttpServlet {
private CityService cityService = new CityService();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int provinceId = Integer.parseInt(request.getParameter("provinceId"));
List<City> cities = cityService.selectByProvinceId(provinceId);
ObjectMapper mapper = new ObjectMapper();
String cityJson = mapper.writeValueAsString(cities);
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print(cityJson);
writer.flush();
writer.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
5. 运行结果
自己遇到的问题
- $.ajax(JSON对象)
传递的是JSON对象。JSON对象:{键:“值”} - dataType: “json”,
json需要用 “” 引用起来,JSON对象里不同的键值是用 ,来分割的 - response.setContentType(“text/html;charset=utf-8”);
charset写错 - 404、500问题