第1章 AJAX
1.1 全局刷新和局部刷新
B/S 结构项目中, 浏览器(Browse)负责把用户的请求和参数通过网络发送给服务器(Server),服务端使用 Servlet(多种服务端技术的一种)接收请求,并将处理结果返回给浏览器。
浏览器在 html,jsp 上呈现数据,混合使用 css, js 帮助美化页面,或响应事件。
1.1.1 全局刷新
登录请求处理:
index.jsp 发起登录请求--------LoginServlet--------result.jsp
发起请求 request 阶段:
浏览器现在内存中是 index 页面的内容和数据 :
服务器端应答结果阶段:
sevlet 返回后把数据全部覆盖掉原来 index 页面内容, result.jsp 覆盖了全部的浏览器内存数据。 整个浏览器数据全部被刷新。重新在浏览器窗口显示数据,样式,标签等
全局刷新原理:
1) 必须由浏览器亲自向服务端发送请求协议包。
2) 这个行为导致服务端直接将【响应包】发送到浏览器内存中
3) 这个行为导致浏览器内存中原有内容被覆盖掉
4) 这个行为导致浏览器在展示数据时候,只有响应数据可以展示
1.1.2 局部刷新
浏览器在展示数据时,此时在窗口既可以看到本次的响应数据, 同时又可以看到浏览器内存中原有数据
局部刷新原理:
1) 不能由浏览器发送请求给服务端
2) 浏览器委托浏览器内存中一个脚本对象代替浏览器发送请求.
3) 这个行为导致导致服务端直接将【响应包】发送脚本对象内存中
4) 这个行为导致脚本对象内容被覆盖掉,但是此时浏览器内存中绝大部分内容没有收到任何影响.
5) 这个行为导致浏览器在展示数据时候,同时展示原有数据和响应数据
AJAX 实现局部刷新的一种技术。
1.2 异步请求对象:
在局部刷新,需要创建一个对象,代替浏览器发起请求的行为,这个对象存在内存中。代替浏览器发起请求并接收响应数据。这个对象叫做异步请求对象。全局刷新是同步行为, 局部刷新是异步行为[浏览器数据没有全部更新]
这个异步对象用于在后台与服务器交换数据。XMLHttpRequest 就是我们说的异步对象。
XMLHttpRequest 对象能够:
• 在不重新加载页面的情况下更新网页
• 在页面已加载后向服务器请求数据
• 在页面已加载后从服务器接收数据
所有现代浏览器 (IE7+、Firefox、Chrome、Safari 以及 Opera) 都内建了 XMLHttpRequest 对象。通过一行简单的 JavaScript 代码,我们就可以创建 XMLHttpRequest 对象
创建 XMLHttpRequest 对象的语法(xhr):
var xmlhttp = new XMLHttpRequest();
AJAX 中的核心对象就是 XMLHttpRequest
1.3 AJAX
1.3.1 什么是 AJAX
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分页面内容的新方法
AJAX 不是新的编程语言,而是使用现有技术混合使用的一种新方法。ajax 中使用的技术有JavaScript, html , dom , xml ,css 等。主要是 JavaScript , XML.
JavaScript: 使用脚本对象 XMLHttpRequest 发送请求, 接收响应数据
XML: 发送和接收的数据格式,现在使用 json
AJAX 不单需要前端的技术,同时需要后端(服务器)的配合。服务器需要提供数据,数据是 AJAX 请求的响应结果。
1.3.2 AJAX 异步实现步骤
XMLHttpRequest 对象介绍
(1) 创建对象方式
var xmlHttp = new XMLHttpRequest();
(2) onreadstatechange 事件
当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。此事件可以指定一个处理函数 function。
通过判断 XMLHttpReqeust 对象的状态,获取服务端返回的数据。
语法:
xmlHttp.onreadystatechange= function() { if( xmlHttp.readyState == 4 && xmlHttp.status == 200){ 处理服务器返回数据 } }
下面是 XMLHttpRequest 对象的三个重要的属性:
属性说明:
onreadystatechange 属性:一个 js 函数名 或 直接定义函数,每当 readyState 属性改变时,就会调用该函数
readyState 属性:
存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
• 0: 请求未初始化,创建异步请求对象 var xmlHttp = new XMLHttpRequest()
• 1: 初始化异步请求对象, xmlHttp.open(请求方式,请求地址,true)
• 2: 异步对象发送请求, xmlHttp.send()
• 3: 异步对象接收应答数据 从服务端返回数据。XMLHttpRequest 内部处理。
• 4: 异步请求对象已经将数据解析完毕。 此时才可以读取数据。
status 属性:
200: "OK"
404: 未找到页面
(3) 初始化请求参数:
方法:
open(method,url,async) : 初始化异步请求对象
参数说明:
• method:请求的类型;GET 或 POST
• url:服务器的 servlet 地址
• async:true(异步)或 false(同步)
例如:
xmlHttp.open(“get”,”http:192.168.1.20:8080/myweb/query”,true)
(4) 发送请求
xmlHttp.send()
(5) 接收服务器响应的数据
如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或responseXML 属性。
responseText:获得字符串形式的响应数据
responseXML:获得 XML 形式的响应数据
1.4 AJAX 实例
1.4.1 全局刷新计算 bmi
需求:计算某个用户的 BMI。 用户在 jsp 输入自己的身高,体重;servlet 中计算 BMI,并显示 BMI 的计算结果和建议。
BMI 指数(即身体质量指数,英文为 BodyMassIndex,简称 BMI),是用体重公斤数除以身高米数平方得出的数字,是目前国际上常用的衡量人体胖瘦程度以及是否健康的一个标准
成人的 BMI 数值:
1)过轻:低于 18.5
2)正常:18.5-23.9
3)过重:24-27
4)肥胖:28-32
5)非常肥胖,高于 32
开发步骤:
1.在 idea 中创建新的工程
名称:ch01-bmi-ajax
2.配置 tomcat 服务器
如果已经配置,省略此步骤。
选择 Local
配置 tomcat 服务器的位置
Module 添加 tomcat 支持
出现窗口
选择 2 Library
确定使用 tomcat
3.创建 jsp
定义 form,有参数 name, weight, height
4.创建 Servlet
名称 BMIServlet
public class BMIServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String strName = req.getParameter("name"); String strWeight = req.getParameter("weight"); String strHeight = req.getParameter("height"); //计算 bmi float weight = Float.parseFloat(strWeight); float height = Float.parseFloat(strHeight); float bmi = weight / (height * height); System.out.println(String.format("%s 的 bmi%s",strName,bmi)); String msg = ""; if( bmi < 18.5 ){ msg = "过瘦"; } else if( bmi >= 18.5 && bmi < 23.9 ){ msg = "正常"; } else if( bmi >=23.9 && bmi <= 27){ msg = "过重"; } else if(bmi > 27 && bmi < 32 ){ msg = "肥胖"; } else { msg="非常肥胖"; } req.setAttribute("msg", strName + "你的 bmi 是"+bmi+","+msg); req.getRequestDispatcher("/result.jsp").forward(req,resp); } }
5.注册 servlet
6.创建 result.jsp
web 目录下创建 result.jsp 文件
7.配置运行程序
输入参数。显示 bmi
1.4.2 使用 HttpServletResponse 响应输出
1.新建 jsp
indexPrint.jsp
2.新建 Servlet
名称 BMIServeltPrint
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 weight = request.getParameter("w"); String height = request.getParameter("h"); //计算bmi float h = Float.valueOf(height); float w = Float.valueOf(weight); float bmi = w / ( h * h); //判断bmi的范围 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 pw = response.getWriter(); pw.println(msg); pw.flush(); pw.close(); } }
3.注册 Servlet
1.4.3 使用 ajax 请求,计算 bmi
1.新建 ajax.jsp
2.在 ajax.jsp 的 head 部分指定 doAjax()函数
3.复制 BMIServletPrint,重新命名 BMIServletAjax
代码不需要改动
4.注册 Servlet
5.在浏览器访问 ajax.jsp
在 BMIServltAjax 的第一行设置断点,然后在 jsp 中点击按钮,发起请求,观察浏览器中的弹出的内容变化
6.修改 ajax.jsp 中的 doAjax()函数
<script type="text/javascript"> function doAjax() { //创建异步对象 var xmlHttp = new XMLHttpRequest(); //绑定事件 xmlHttp.onreadystatechange = function () { alert( "处理请求的状态:" + xmlHttp.readyState + "|服务器端返回数据:"+xmlHttp.responseText); } //初始化参数 xmlHttp.open("get","bmiAjax?name=张三&height=1.8&weight=75",true); //发送 ajax 异步请求 xmlHttp.send(); } </script>
7.访问 ajax.jsp 请求
在 jsp 中点击按钮,发起请求,观察浏览器中的弹出的内容变化
8.获取 dom 对象 value 值
<script type="text/javascript"> function doAjax() { //创建异步对象 var xmlHttp = new XMLHttpRequest(); //绑定事件 xmlHttp.onreadystatechange = function () { alert( "处理请求的状态:" + xmlHttp.readyState + "|服务器端返回数据:"+xmlHttp.responseText); } //初始化参数 //获取页面 dom 中的数据 var name = document.getElementById("name").value; var height = document.getElementById("height").value; var weight = document.getElementById("weight").value; var param = "name="+name+"&height="+height+"&weight="+weight; xmlHttp.open("get","bmiAjax?"+param,true); //发送 ajax 异步请求 xmlHttp.send(); } </script>
9. 在浏览器测试发送 ajax 请求
10.修改 doAjax 函数
<script type="text/javascript"> function doAjax() { //创建异步对象 var xmlHttp = new XMLHttpRequest(); //绑定事件 xmlHttp.onreadystatechange = function () { if( xmlHttp.readyState == 4 && xmlHttp.status == 200){ var data = xmlHttp.responseText document.getElementById("dataDiv").innerText = data; } } //初始化参数 //获取页面 dom 中的数据 var name = document.getElementById("name").value; var height = document.getElementById("height").value; var weight = document.getElementById("weight").value; var param = "name="+name+"&height="+height+"&weight="+weight; xmlHttp.open("get","bmiAjax?"+param,true); //发送 ajax 异步请求 xmlHttp.send(); } </script>
1.4.4 根据省份 id 查询省份名称
需求:用户在文本框架输入省份的编号 id,在其他文本框显示省份名称
项目环境准备:
1)数据库:springdb
2)数据表:
省份信息表:
SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `province`; CREATE TABLE `province` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL COMMENT '省份名称', `jiancheng` varchar(255) DEFAULT NULL COMMENT '简称', `shenghui` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8; INSERT INTO `province` VALUES ('1', '河北', '冀', '石家庄'); INSERT INTO `province` VALUES ('2', '山西', '晋', '太原市'); INSERT INTO `province` VALUES ('3', '内蒙古', '蒙', '呼和浩特市 '); INSERT INTO `province` VALUES ('4', '辽宁', '辽', '沈阳'); INSERT INTO `province` VALUES ('5', '江苏', '苏', '南京'); INSERT INTO `province` VALUES ('6', '浙江', '浙', '杭州'); INSERT INTO `province` VALUES ('7', '安徽', '皖', '合肥'); INSERT INTO `province` VALUES ('8', '福建', '闽', '福州'); INSERT INTO `province` VALUES ('9', '江西', '赣', '南昌');
城市信息表:
SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `city`; CREATE TABLE `city` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `provinceid` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8; INSERT INTO `city` VALUES ('1', '石家庄市', '1'); INSERT INTO `city` VALUES ('2', '秦皇岛', '1'); INSERT INTO `city` VALUES ('3', '保定市', '1'); INSERT INTO `city` VALUES ('4', '张家口', '1'); INSERT INTO `city` VALUES ('5', '南昌市', '9'); INSERT INTO `city` VALUES ('6', '九江市', '9'); INSERT INTO `city` VALUES ('7', '宜春市', '9'); INSERT INTO `city` VALUES ('8', '福州市', '8'); INSERT INTO `city` VALUES ('9', '厦门市', '8'); INSERT INTO `city` VALUES ('10', '泉州市', '8'); INSERT INTO `city` VALUES ('11', '龙岩市', '8'); INSERT INTO `city` VALUES ('12', '太原', '2'); INSERT INTO `city` VALUES ('13', '大同', '2'); INSERT INTO `city` VALUES ('14', '呼和浩特', '3'); INSERT INTO `city` VALUES ('15', '包头', '3'); INSERT INTO `city` VALUES ('16', '呼伦贝尔', '3');
项目结构:
项目是一个 web 应用, index.jsp 发送请求, SearchServlet 接收请求, 调用 ProvinceDao
从数据库获取指定 id 的省份名称
实现步骤:
1. 在 idea 新建 web application
项目名称 ajaxweb
2. 配置 tomcat 服务器
3. 在 index.jsp 中创建 XMLHttpRequest 对象
定义表单:
4.创建 XMLHttpRequest 对象
5. 创建 Servlet 处理 Ajax 请求
6. web.xml 文件,注册 servlet
<servlet> <servlet-name>SearchServletservlet-name> <servlet-class>com.bjpowernode.controller.SearchServletservlet-class> servlet> <servlet-mapping> <servlet-name>SearchServletservlet-name> <url-pattern>/searchProvinceurl-pattern> servlet-mapping>
7. 发布应用到 tomcat 服务器,在浏览器访问 index.jsp,得到省份名称
8. 添加 mysql 驱动
可以在WEB-INF目录下创 建 lib文件 , 用来存放 jar文件 , 把 准 备 好的mysql-connector-java-5.1.6.jar 拷贝到 lib 目录下。
在 Project Structure 窗口中,选择你的 modules,选择 Dependencies
确认修改:
点击“Fix”后选择 Add lib to the artifact
9. 创建类 ProvinceDao 访问数据库
方法定义:
定义变量:
访问数据库:
finally 关闭资源
返回结果:
10. 修改之前创建的 Servlet
11. 修改 index.jsp 的 js 代码
12. 部署项目,在浏览器访问应用
1.4.5 使用 json 作为数据交换格式
需求:根据省份编号 id,查询省份的全部数据,数据格式 json
项目结构:
实现步骤:
1. 添加处理 json 的工具库
jackson:是非常有名的处理 json 的工具库。使用 jackson 可以实现 java 对象到 json 格式字符串的转换,也可以实现 json 字符串转为 json 对象。
把下面三个 jar 文件复制到/WEB-INF/lib 目录中。
其他步骤同 添加 mysql 驱动
2. 创建实体类 Province
3. 在 ProvinceDao 中增加方法,返回对象
方法定义:
数据库操作:
其他代码同 selectProvinceName()方法。
4. 创建新的 Servlet 对象
5. 创建 searchJson.jsp,获取 json 数据
页面定义:
AJAX 请求处理:
6. 部署应用,浏览器访问
1.4.6 异步请求
XMLHttpRequest 对象 open( method , url, true ) 第三个参数 true 表示异步请求
异步请求特点:
1)某一个时刻,浏览器可以委托多个异步请求对象发送请求,无需等待请求处理完成。
2)浏览器委托异步请求对象工作期间,浏览器处于活跃状态。可以继续向下执行其他命令。
3) 当响应就绪后再对响应结果进行处理
实现步骤:
1. 设置异步对象 open 方法第三个参数为 true
//初始请求参数 xmlHttp.open("get","searchProvinceJson?proid="+proid,true);
2. send()后面,增加 alert()
//发送请求 xmlHttp.send(); alert("我是在异步请求之后的执行代码")
3.SearchServletJson 类的 doGet 方法第一个加入断点
4.部署应用,在浏览器访问应用。
点击“搜索”按钮,请求发送到 Servlet,程序暂停执行, js 中 alert 执行继续执行,没有等待请求处理完成,浏览器窗口弹窗“我是在异步请求之后的执行代码”字符串。
1.4.7 同步请求
XMLHttpRequest 对象 open( method , url, false ) 第三个参数 false 表示同步请求同步请求特点:
1)某一个时刻,浏览器只能委托一个异步请求对象发送请求,必须等待请求处理完成。
2)浏览器委托异步请求对象工作期间,浏览器处于等待状态。不能执行其他命令。
3)不推荐使用。
实现步骤:同 1.4.3 步骤,需要 open(method,url,false)第三个参数设为 false
1.5练习
1. 在文本框内输入省份名称中的某几个字,把符合条件的省份名称显示一个
5.在浏览器访问 ajax.jsp
在 BMIServltAjax 的第一行设置断点,然后在 jsp 中点击按钮,发起请求,观察浏览器中的弹
出的内容变化
6.修改 ajax.jsp 中的 doAjax()函数