思维导图
一、全局刷新和局部刷新
全局刷新: 整个浏览器被新的数据覆盖。在网络中传输大量的数据。浏览器需要加载,渲染画面。
局部刷新: 在浏览器的内部,发起请求,获取网络改变页面中的部分内容。其余的页面无需加载和渲染。网络中数据传输量少,给用户的感受好。
Ajax的核心就是局部刷新,局部刷新使用的核心对象是 异步对象(XMLHttpRequest)
这个异步对象是存在浏览器内存中的,使用JavaScript语法创建和使用XMLHttpRequest对象。
二、Ajax
1、概述
ajax: Asynchronous Javascript and XML (异步JavaScript和XML)
ajax 是一种做局部刷新的新方法(2003年左右),不是一门语言。ajax包含的技术主要有JavaScript、dom、css、xml等。核心是JavaScript和xml。
JavaScript: 负责创建异步对象,发送请求,更新页面的dom对象。ajax请求需要服务器端的数据。
xml: 网络中的传输的数据格式。使用json替换了xml。
2、Ajax异步实现步骤
XMLHttpRequest对象介绍
(1)创建对象方式
var xmlHttp = new XMLHttpRequest();
(2)onreadstatechange事件
给异步对象绑定事件。onreadstatechange:当异步对象发起请求,获取了数据都会触发这个事件。这个事件需要指定一个函数,在函数中处理状态的变化。
xmlHttp.onreadystatechange = function {
//处理请求的状态变化。
if (xmlHttp.readyState == 4 && statue == 200) {
//可以处理服务器端的数据,更新当前页面
var data = xmlHttp.responseText;
document.getElementById("name").value = data;
}
}
异步对象的属性readyState表示异步对象内部使用,获取了原始的数据
0:创建异步对象时, new XMLHttpRequest();
1:初始化异步请求对象,xmlHttp.open();
2:发送请求,xmlHttp.send();
3:从服务器端获取了数据,此时3,注意3是异步对象内部使用,获取了原始的数据;
4:异步对象把接收的数据处理完成后。此时开发人员在4的时候处理数据。
异步对象的status属性,表示网络请求的状况的,200,404,500,需要是当status==200时,表示网络请求是成功的。
(3)初始异步请求对象
异步的方法open().
xmlHttp.open(请求方式get|post,“服务器端的访问地址”,同步|异步请求(默认是true,异步请求));
//例如
xmlHttp.open("get", "loginServlet?name=zs&pwd=123", true);
(4)使用异步对象发送请求
//例如
xmlHttp.send();
获取服务器端返回的数据,使用异步对象的属性 responseText。
xmlHttp.responseText;
3、Demo1(计算BMI)
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>局部刷新</title>
<script>
//使用内存中的异步对象,代替浏览器发起请求。异步对象使用js创建和管理的
function doAjax() {
//1 创建异步对象
var xmlHttp = new XMLHttpRequest();
//2 绑定事件
xmlHttp.onreadystatechange = function () {
//处理服务器端返回的数据,更新当前页面
// alert("readystate属性值======" + xmlHttp.readyState)
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
// alert(xmlHttp.responseText);
var data = xmlHttp.responseText;
//更新dom对象,更新页面数据
document.getElementById("mydata").innerText = data;
}
}
//3 初始请求数据
//获取dom对象的value属性值
var name = document.getElementById("name").value;
var w = document.getElementById("w").value;
var h = document.getElementById("h").value;
var param = "name="+name + "&w="+w+"&h="+h;
// alert("param="+param);
xmlHttp.open("get","bmiAjax?"+param,true);
//4 发起请求
xmlHttp.send();
}
</script>
</head>
<body>
<p>局部刷新</p>
<div>
<!--没有使用form-->
姓名:<input type="text" id="name"><br>
体重(公斤):<input type="text" id="w"><br>
身高(米):<input type="text" id="h"><br>
<input type="button" value="计算bmi" onclick="doAjax()">
<br>
<br>
<div id="mydata">等待加载数据...</div>
</div>
</body>
</html>
BmiAjaxServlet.java
package com.lyh.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class BmiAjaxServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("=====接收了ajax的请求=====");
//接受请求参数
String strName = request.getParameter("name");
String height = request.getParameter("h");
String weight = request.getParameter("w");
float h = Float.valueOf(height);
float w = Float.valueOf(weight);
float bmi = w / (h * h);
String msg = "";
if(bmi <= 18.5){
msg = "您比较瘦";
}else if(bmi > 18.5 && bmi <= 23.9) {
msg = "您的bmi是正常的";
}else if(bmi > 24 && bmi <= 27) {
msg = "您的身体比较胖";
}else {
msg = "你的身体肥胖";
}
System.out.println("msg="+msg);
msg = "您好:"+strName+"先生/女士,您的bmi值是:"+bmi+","+msg;
//
//响应ajax需要的数据,使用HttpServletResponse输出数据
response.setContentType("text/html;charset=utf-8");
//获取PrintWriter
PrintWriter pw = response.getWriter();
//输出数据
pw.println(msg);
//清空缓存
pw.flush();
//关闭close
pw.close();
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>BmiAjaxServlet</servlet-name>
<servlet-class>com.lyh.controller.BmiAjaxServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BmiAjaxServlet</servlet-name>
<url-pattern>/bmiAjax</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
4、Demo2(连接数据库查询)
数据库记录
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>ajax根据省份id获取形成</title>
<script>
function search() {
//发起ajax请求,传递参数给服务器,服务器返回数据
//1 创建异步对象
var xmlHttp = new XMLHttpRequest();
//2 绑定事件
xmlHttp.onreadystatechange = function () {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
document.getElementById("proname").value = xmlHttp.responseText;
}
}
//3 初始异步对象
//获取proid文本框的值
var proid = document.getElementById("proid").value;
xmlHttp.open("get","queryProvince?proid="+proid, true);
//4 发送请求
xmlHttp.send();
}
</script>
</head>
<body>
<p>ajax根据省份id获取名称</p>
<table>
<tr>
<td>省份编号:</td>
<td>
<input type="text" id="proid">
<input type="button" value="搜索" onclick="search()">
</td>
</tr>
<tr>
<td>省份名称:</td>
<td><input type="text" id="proname" readonly></td>
</tr>
</table>
</body>
</html>
ProvinceDao.java
package com.lyh.dao;
import jdk.nashorn.internal.objects.annotations.Where;
import javax.xml.transform.Result;
import java.sql.*;
//使用JDBC访问数据库
public class ProvinceDao {
//根据id获取名称
public String queryProvinceNameById(Integer provinceId) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
String sql = "";
String url = "jdbc:mysql://localhost:3306/springdb";
String username = "root";
String password = "123456";
String name = "";
//加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, username, password);
//创建PreparedStatement
sql = "select name from pro where id = ?";
pst = conn.prepareStatement(sql);
//设置参数值
pst.setInt(1, provinceId);
//执行sql
rs = pst.executeQuery();
//遍历rs
while (rs.next()) { //当rs中有多于1条记录时
name = rs.getString("name");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
if( rs != null) {
rs.close();
}
if(pst != null) {
pst.close();
}
if(conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return name;
}
}
QueryProvinceServlet.java
package com.lyh.controller;
import com.lyh.dao.ProvinceDao;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class QueryProvinceServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
//处理get请求
String strProid = req.getParameter("proid");
System.out.println("strProid:" + strProid);
String name = "默认是无数据";
//访问dao
if(strProid != null && !"".equals(strProid.trim())) {
ProvinceDao dao = new ProvinceDao();
name = dao.queryProvinceNameById(Integer.valueOf(strProid));
}
//使用HttpServletResponse输出数据
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
pw.println(name);
pw.flush();
pw.close();
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>QueryProvince</servlet-name>
<servlet-class>com.lyh.controller.QueryProvinceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>QueryProvince</servlet-name>
<url-pattern>/queryProvince</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
5、Demo3(返回json格式数据)
json的优点:
- json的格式好理解
- json格式数据在多种语言中,比较容易处理。使用java、JavaScript读写json格式的数据比较容易
- json格式数据占用空间小,在网络中的传输快,用户体验好
json的工具库:
- gson(google)
- fastjson:速度快,不是最符合json处理规范的
- jackson:性能好,规范好
- json-lib:性能差,依赖多
myajax.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用json格式的数据</title>
<script>
function doSearch() {
//1. 创建异步对象
var xmlHttp = new XMLHttpRequest();
//2.绑定事件
xmlHttp.onreadystatechange = function () {
if(xmlHttp.readyState ==4 && xmlHttp.status==200){
var data = xmlHttp.responseText;
//eval是执行括号中的代码,把json字符串转为json对象
var jsonobj = eval("(" + data + ")");
//更新dom对象
callback(jsonobj);
}
}
//3.初始异步对象的请求参数
var proid = document.getElementById("proid").value;
xmlHttp.open("get","queryJsonServlet?proid="+proid,true);
//4.发送请求
xmlHttp.send();
}
//定义函数,处理服务器端返回的数据
function callback(json) {
document.getElementById("proname").value = json.name;
document.getElementById("projiancheng").value = json.jiancheng;
document.getElementById("proshenghui").value = json.shenghui;
}
</script>
</head>
<body>
<p>ajax请求使用json格式的数据</p>
<table>
<tr>
<td>省份编号:</td>
<td>
<input type="text" id="proid">
<input type="button" value="搜索" onclick="doSearch()">
</td>
</tr>
<tr>
<td>省份名称:</td>
<td><input type="text" id="proname"></td>
</tr>
<tr>
<td>省份简称:</td>
<td><input type="text" id="projiancheng"></td>
</tr>
<tr>
<td>省会名称:</td>
<td><input type="text" id="proshenghui"></td>
</tr>
</table>
</body>
</html>
QueryJsonServlet.java
package com.lyh.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lyh.dao.ProvinceDao;
import com.lyh.entity.Province;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class QueryJsonServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String json = "{}";
//获取请求参数,省份id
String strProid = request.getParameter("proid");
//判断proid有值时,调用dao查询
if (strProid != null && strProid.trim().length() > 0) {
ProvinceDao dao = new ProvinceDao();
Province p = dao.queryProvinceById(Integer.valueOf(strProid));
//需要使用jackson 把 province对象转为json
ObjectMapper om = new ObjectMapper();
json = om.writeValueAsString(p);
}
//指定服务器端(Servlet)返回给浏览器的是json格式数据
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json); //输出数据---会赋给ajax中 responseText属性
pw.flush();
pw.close();
}
}
Province.java
package com.lyh.entity;
public class Province {
private Integer id;
private String name;
private String jiancheng;
private String shenghui;
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 String getJiancheng() {
return jiancheng;
}
public void setJiancheng(String jiancheng) {
this.jiancheng = jiancheng;
}
public String getShenghui() {
return shenghui;
}
public void setShenghui(String shenghui) {
this.shenghui = shenghui;
}
}
ProvinceDao.java
//根据id获取一个完整的Province对象
public Province queryProvinceById(Integer provinceId) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
String sql = "";
String url = "jdbc:mysql://localhost:3306/springdb";
String username = "root";
String password = "123456";
Province province = null;
//加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, username, password);
//创建PreparedStatement
sql = "select id, name, jiancheng, shenghui from pro where id = ?";
pst = conn.prepareStatement(sql);
//设置参数值
pst.setInt(1, provinceId);
//执行sql
rs = pst.executeQuery();
//遍历rs
while (rs.next()) { //当rs中有多于1条记录时
province = new Province();
province.setId(rs.getInt("id"));
province.setName(rs.getString("name"));
province.setJiancheng(rs.getString("jiancheng"));
province.setShenghui(rs.getString("shenghui"));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
if( rs != null) {
rs.close();
}
if(pst != null) {
pst.close();
}
if(conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return province;
}
6、异步与同步
xmlHttp.open("get","queryJsonServlet?proid="+proid,true);
true:异步处理请求。使用异步对象发起请求后,不用等级数据处理完毕,就可以执行其他的操作。 也可以创建其他的XMLHttpRequest,发送其他的请求处理
false: 同步,异步对象必须处理完成请求,从服务端获取数据后,才能执行send之后的代码。任意时刻只能执行一个异步请求。