Ajax
1.什么是Ajax?
asynchronous javascript and xml:异步的js和xml
它能使用js访问服务器,而且是异步访问!
服务器给客户端的响应一般是整个页面,一个html完整页面!但在ajax中因为是局部刷新,那么服务器就不用再响应整个页面!而只是数据!
>text:纯文本
>xml:
>json:它是js提供的数据交互格式,在Ajax中最受欢迎!
2.异步交互和同步交互
* 同步:
>发一个请求,就要等待服务器的响应结束,然后才能发第二个请求!中间这段时间就是一个“卡”
>刷新的是整个页面!
* 异步:
>发送一个请求后,无需等待服务器的响应,然后就可以发送第二个请求!
>可以使用js接收服务器的响应,然后使用js来局部刷新!
3.ajax应用场景
* 百度的搜索框
* 用户注册时(校验用户名是否被注册过)
4.ajax的优缺点
优点:
* 异步交互:增强了用户体验!
* 性能:因为服务器无需再响应整个页面,只需要响应部分内容,所以服务器的压力减轻了!
缺点:
* ajax不能应用在所有的场景!
* ajax无端的增多了对服务器的访问次数,给服务器带来了压力!
Ajax发送异步请求(四步操作)
1.第一步(得到XMLHttpRequest)
* ajax其实只需要学习一个对象:XMLHttpRequest,如果掌握了它,就掌握了ajax!!!
* 得到XMLHttpRequest
> 大多数浏览器都支持:var xmlHttp = new XMLHttpRequest();
> IE6.0:var xmlHttp = new ActiveXObject("Msxml2.0XMLHTTP");
> IE5.5及更早版本的IE:var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
* 编写创建XMLHttpRequest对象的函数
function creatXMLHttpRequest(){ try { return new XMLHttpRequest(); } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("不晓得你用的什么浏览器!"); throw e; } } } }
2.第二步(打开与服务器的连接)
* xmlHttp.open():用来打开与服务器的连接,它需要三个参数:
> 请求方式:可以是GET或POST
> 请求的URL:指定服务器端资源,例如:/day23_1/AServlet
> 请求是否为异步:如果为true表示发送异步请求,否则同步请求!
* xmlHttp.open("GET", "/day23_1/AServlet", true);
3.第三步(发送请求)
* xmlHttp.send(null):如果不给可能会造成部分浏览器无法发送!
>参数:就是请求体内容!如果是GET请求,必须给出null。
4.第四步()
*在xmlHttp对象的一个事件上注册监听器:onreadystatechange
* xmlHttp对象一共有5个状态:
> 0状态:刚创建,还没有调用open()方法;
> 1状态:请求开始,调用了open()方法,但还没有调用send()方法
> 2状态:调用完了send()方法了;
> 3状态:服务器已经开始响应,但不表示响应结束了。
> 4状态:服务器响应结束!(通常我们只关心最后这个状态!!!)
* 得到xmlHttp对象的状态:
> var state = xmlHttp.readyState;//可能是0、1、2、3、4
* 得到服务器响应的状态吗
> var status = xmlHttp.status;//例如为200、404、500
* 得到服务器响应的内容
> var content = xmlHttp.responseText;//得到服务器的响应的文本格式的内容
> var content = xmlHttp.responseXML;//得到服务器的响应的XML响应的内容,它是Document对象了!
xmlHttp.onreadystatechange = function(){//xmlHttp的5种状态都会调用本方法 if(xmlHttp.readyState == 1 && xmlHttp.status == 200){//双重判断:判读是否为4状态,而且还有判断是否为200 //获取服务器响应内容 var text=xmlHttp.responseText; } };
JS示例:
<head> <script type="text/javascript"> window.onload=function(){//在文档加载完 成之后马上执行! //的带btn元素 var btn=document.getElementById("btn"); //给btn的click事件注册监听 btn.onclick=function(){//在按钮被点击时执行! //获取h1元素对应的DOM对象 var h1=document.getElementById("h1"); //给h1添加内容 h1.innerHTML="hello JS!!"; }; }; </script> </head> <body> <button id="btn">点击这里</button> <h1 id="h1"></h1> </body>
Ajax第一例:
AServlet:
package com.xjs.web.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("Hello AJAX!"); response.getWriter().print("Hello AJAX!"); } }
ajax1.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'ajax1.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script type="text/javascript"> //创建异步对象 function createXMLHttpRequest() { try { return new XMLHttpRequest(); } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("不晓得你用的什么浏览器!"); throw e; } } } } window.onload = function() {//文档加载完毕后执行 var btn = document.getElementById("btn"); btn.onclick = function() {//给按钮的点击事件注册监听 /* ajax四步操作,得到服务器的响应 把响应结果显示到h1元素中 */ //1.得到异步对象 var xmlHttp = createXMLHttpRequest(); //2.打开与服务器 的连接 xmlHttp.open("GET", "/day23_1/AServlet", true); //3.发送请求 xmlHttp.send(null); //4.给异步对象的ontreadystatechange事件注册监听器 xmlHttp.onreadystatechange = function() {//当xmlHttp的状态发生变化时执行 if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { //获取服务器的响应内容 var text = xmlHttp.responseText; //获取h1元素 var h1 = document.getElementById("h1"); h1.innerHTML = text; } }; }; }; </script> </head> <body> <button id="btn">点击这里</button> <h1 id="h1"></h1> </body> </html>
第二例:发生POST请求(如果发送请求时需要带有参数,一般都用POST请求)
*open:xmlHttp.open("POST", ....);
*添加一步:设置Content-Type请求头:
> xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
*send:xmlHttp.send("username=zhangSan&password=123");//发送请求时指定请求体
AServlet:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=utf-8"); String username = request.getParameter("username"); System.out.println("(POST)Hello AJAX! "+username); response.getWriter().print(username); }
ajax2.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'ajax1.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script type="text/javascript"> //创建异步对象 function createXMLHttpRequest() { try { return new XMLHttpRequest(); } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("不晓得你用的什么浏览器!"); throw e; } } } } window.onload = function() {//文档加载完毕后执行 var btn = document.getElementById("btn"); btn.onclick = function() {//给按钮的点击事件注册监听 /* ajax四步操作,得到服务器的响应 把响应结果显示到h1元素中 */ //1.得到异步对象 var xmlHttp = createXMLHttpRequest(); //2.打开与服务器 的连接 /*****************修改open方法,指定请求方式为POST*******************/ xmlHttp.open("POST", "<c:url value='/AServlet'/>", true); /********设置请求头:Content-Type*********/ xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //3.发送请求 /************发送时指定请求体*************/ xmlHttp.send("username=金泰妍");//GET请求没有请求体,但也要给出null,不然FireFox可能会不能发送! //4.给异步对象的ontreadystatechange事件注册监听器 xmlHttp.onreadystatechange = function() {//当xmlHttp的状态发生变化时执行 if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { //获取服务器的响应内容 var text = xmlHttp.responseText; //获取h1元素 var h1 = document.getElementById("h1"); h1.innerHTML = text; } }; }; }; </script> </head> <body> <button id="btn">点击这里</button> <h1 id="h1"></h1> </body> </html>
第三例:注册表单之校验用户是否注册!
1.编写页面:
* ajax3.jsp
>给出注册表单页面
>给用户名文本框添加onblur事件的监听
>获取文本框的内容,通过ajax 4步发送给服务器,得到响应结果
* 如果为1:在文本框后面显示 “用户名已被注册”
* 如果为0:什么都不做!
2.编写Servlet
* ValidateUsernameServlet
> 获取客户端传递的用户名参数
> 判断是否为itcast
* 是:返回1
* 否:返回0
ValidateUsernameServlet.java:
package com.xjs.web.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ValidateUsernameServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); request.setCharacterEncoding("UTF-8"); /* * 1.获取参数username 2.判断是否为itcast 3.是:响应1 4.否:响应0 */ String username = request.getParameter("username"); System.out.println(username); if (username.equalsIgnoreCase("itcast")) { System.out.println("1"); response.getWriter().print("1"); } else { System.out.println("0"); response.getWriter().print("0"); } } }
ajax3.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'ajax3.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script type="text/javascript"> //创建异步对象 function createXMLHttpRequest() { try { return new XMLHttpRequest(); } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("不晓得你用的什么浏览器!"); throw e; } } } } window.onload = function() { //获取文本框,给它的失去焦点事件注册监听 var userEle = document.getElementById("usernameEle"); userEle.onblur = function() { //1.得到异步对象 var xmlHttp = createXMLHttpRequest(); //2.打开连接 xmlHttp.open("POST", "<c:url value='/ValidateUsernameServlet'/>", true); //3.设置请求头:Content-Type xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //4.发送请求,给出请求体 xmlHttp.send("username=" + userEle.value); //5.给xmlHttp的onreadystatechange事件注册监听 xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { //获取服务器的响应,判断是否为1 //是:获取span,添加内容:“用户名已被注册”; var text = xmlHttp.responseText; var span = document.getElementById("errorSpan"); if (text == "1") { //得到span元素 span.innerHTML = "用户名已被注册!"; } else { span.innerHTML = ""; } } }; }; }; </script> </head> <body> <h1>演示用户名是否已被注册</h1> <form action="" method="post"> 用户名:<input type="text" name="username" id="usernameEle" /><span id="errorSpan"></span><br> 密码:<input type="password" name="password" /><br> <input type="submit" value="注册" /> </form> </body> </html>
第四例: 响应内容为xml数据
* 服务器端:
> 设置响应头:Content-Type,其值为:text/xml; charset=utf-8
* 客户端:
> var doc = xmlHttp.responseXML; //得到的是Document对象!
BServlet:
package com.xjs.web.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/xml;charset=utf-8"); String xml="<students>"+ "<student number='ITCAST_1001'>"+ "<name>金泰妍</name>"+ "<age>23</age>"+ "<sex>女</sex>"+ "</student>"+ "</students>"; response.getWriter().print(xml); } }
ajax4.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'ajax1.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script type="text/javascript"> //创建异步对象 function createXMLHttpRequest() { try { return new XMLHttpRequest(); } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("不晓得你用的什么浏览器!"); throw e; } } } } window.onload = function() {//文档加载完毕后执行 var btn = document.getElementById("btn"); btn.onclick = function() {//给按钮的点击事件注册监听 /* ajax四步操作,得到服务器的响应 把响应结果显示到h1元素中 */ //1.得到异步对象 var xmlHttp = createXMLHttpRequest(); //2.打开与服务器 的连接 xmlHttp.open("GET", "/day23_1/BServlet", true); //3.发送请求 xmlHttp.send(null); //4.给异步对象的ontreadystatechange事件注册监听器 xmlHttp.onreadystatechange = function() {//当xmlHttp的状态发生变化时执行 if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { //获取服务器的响应内容(XML) var doc = xmlHttp.responseXML; //查询文档下名为student的所有元素,得到数组,再取下标0元素 var ele = doc.getElementsByTagName("student")[0]; var number=ele.getAttribute("number");//获取元素名为number的属性值 var name=ele.getElementsByTagName("name")[0].textContent;//IE支持 var age=ele.getElementsByTagName("age")[0].textContent; var sex=ele.getElementsByTagName("sex")[0].textContent; var text=number+","+name+","+age+","+sex; document.getElementById("h1").innerHTML=text; } }; }; }; </script> </head> <body> <button id="btn">点击这里</button> <h1 id="h1"></h1> </body> </html>
第五例:省市联动
1.页面
<select name="province">
<option>===请选择省份===</option>
</select>
<select name="city">
<option>===请选择城市===</option>
</select>
2.ProvinceServlet
* ProvinceServlet:当页面加载完毕后马上请求这个Servlet!
> 它需要加载china.xml文件,把所有的省的名称使用字符串发送给客户端!
3.页面的工作
* 获取这个字符串,使用逗号分隔,得到数组
* 循环遍历每个字符串(省份的名称),使用每个字符串创建一个<option>元素添加到<select name="province">这个元素中
4.CityServlet
* CityServlet:当页面选择某个省时,发送请求!
* 得到省份的名称,加载china.xml文件,查询出该省份对应的元素对象!把这个元素转换成xml字符串,发送给客户端
5.页面的工作
* 把<select name="city">中的所有子元素删除,但不要删除<option>===请选择城市===</option>
* 得到服务器的响应结果:doc!!!
* 获取所有的<city>子元素,循环遍历,得到<city>的内容
* 使用每个<city>的内容创建一个<option>元素,添加到<select name="city">
省份在src下的china.xml:
<?xml version="1.0" encoding="utf-8"?> <china> <province name="北京"> <city>东城区</city> <city>西城区</city> <city>崇文区</city> <city>宣武区</city> <city>朝阳区</city> <city>丰台区</city> <city>石景山区</city> <city>海淀区</city> <city>门头沟区</city> <city>房山区</city> <city>通州区</city> <city>顺义区</city> <city>昌平区</city> <city>大兴区</city> <city>怀柔区</city> <city>平谷区</city> <city>密云县</city> <city>延庆县</city> </province> <province name="天津"> <city>和平区</city> <city>河东区</city> <city>河西区</city> <city>南开区</city> <city>河北区</city> <city>红桥区</city> <city>塘沽区</city> <city>汉沽区</city> <city>大港区</city> <city>东丽区</city> <city>西青区</city> <city>津南区</city> <city>北辰区</city> <city>武清区</city> <city>宝坻区</city> <city>宁河县</city> <city>静海县</city> <city>蓟县</city> </province> <province name="河北"> <city>石家庄</city> <city>唐山</city> <city>秦皇岛</city> <city>邯郸</city> <city>邢台</city> <city>保定</city> <city>张家口</city> <city>承德</city> <city>沧州</city> <city>廊坊</city> <city>衡水</city> </province> <province name="山西"> <city>太原</city> <city>大同</city> <city>阳泉</city> <city>长治</city> <city>晋城</city> <city>朔州</city> <city>晋中</city> <city>运城</city> <city>忻州</city> <city>临汾</city> <city>吕梁</city> </province> <province name="内蒙古"> <city>呼和浩特</city> <city>包头</city> <city>乌海</city> <city>赤峰</city> <city>通辽</city> <city>鄂尔多斯</city> <city>呼伦贝尔</city> <city>巴彦淖尔</city> <city>乌兰察布</city> <city>兴安盟</city> <city>锡林郭勒盟</city> <city>阿拉善盟</city> </province> <province name="辽宁"> <city>沈阳</city> <city>大连</city> <city>鞍山</city> <city>抚顺</city> <city>本溪</city> <city>丹东</city> <city>锦州</city> <city>营口</city> <city>阜新</city> <city>辽阳</city> <city>盘锦</city> <city>铁岭</city> <city>朝阳</city> <city>葫芦岛</city> </province> <province name="吉林"> <city>长春</city> <city>吉林</city> <city>四平</city> <city>辽源</city> <city>通化</city> <city>白山</city> <city>松原</city> <city>白城</city> <city>延边</city> </province> <province name="黑龙江"> <city>哈尔滨</city> <city>齐齐哈尔</city> <city>鸡西</city> <city>鹤岗</city> <city>双鸭山</city> <city>大庆</city> <city>伊春</city> <city>佳木斯</city> <city>七台河</city> <city>牡丹江</city> <city>黑河</city> <city>绥化</city> <city>大兴安岭</city> </province> <province name="上海"> <city>黄浦区</city> <city>卢湾区</city> <city>徐汇区</city> <city>长宁区</city> <city>静安区</city> <city>普陀区</city> <city>闸北区</city> <city>虹口区</city> <city>杨浦区</city> <city>闵行区</city> <city>宝山区</city> <city>嘉定区</city> <city>浦东新区</city> <city>金山区</city> <city>松江区</city> <city>青浦区</city> <city>南汇区</city> <city>奉贤区</city> <city>崇明县</city> </province> <province name="江苏"> <city>南京</city> <city>无锡</city> <city>徐州</city> <city>常州</city> <city>苏州</city> <city>南通</city> <city>连云港</city> <city>淮安</city> <city>盐城</city> <city>扬州</city> <city>镇江</city> <city>泰州</city> <city>宿迁</city> </province> <province name="浙江"> <city>杭州</city> <city>宁波</city> <city>温州</city> <city>嘉兴</city> <city>湖州</city> <city>绍兴</city> <city>金华</city> <city>衢州</city> <city>舟山</city> <city>台州</city> <city>丽水</city> </province> <province name="安徽"> <city>合肥</city> <city>芜湖</city> <city>蚌埠</city> <city>淮南</city> <city>马鞍山</city> <city>淮北</city> <city>铜陵</city> <city>安庆</city> <city>黄山</city> <city>滁州</city> <city>阜阳</city> <city>宿州</city> <city>巢湖</city> <city>六安</city> <city>亳州</city> <city>池州</city> <city>宣城</city> </province> <province name="福建"> <city>福州</city> <city>厦门</city> <city>莆田</city> <city>三明</city> <city>泉州</city> <city>漳州</city> <city>南平</city> <city>龙岩</city> <city>宁德</city> </province> <province name="江西"> <city>南昌</city> <city>景德镇</city> <city>萍乡</city> <city>九江</city> <city>新余</city> <city>鹰潭</city> <city>赣州</city> <city>吉安</city> <city>宜春</city> <city>抚州</city> <city>上饶</city> </province> <province name="山东"> <city>济南</city> <city>青岛</city> <city>淄博</city> <city>枣庄</city> <city>东营</city> <city>烟台</city> <city>潍坊</city> <city>济宁</city> <city>泰安</city> <city>威海</city> <city>日照</city> <city>莱芜</city> <city>临沂</city> <city>德州</city> <city>聊城</city> <city>滨州</city> <city>荷泽</city> </province> <province name="河南"> <city>郑州</city> <city>开封</city> <city>洛阳</city> <city>平顶山</city> <city>安阳</city> <city>鹤壁</city> <city>新乡</city> <city>焦作</city> <city>濮阳</city> <city>许昌</city> <city>漯河</city> <city>三门峡</city> <city>南阳</city> <city>商丘</city> <city>信阳</city> <city>周口</city> <city>驻马店</city> </province> <province name="湖北"> <city>武汉</city> <city>黄石</city> <city>十堰</city> <city>宜昌</city> <city>襄樊</city> <city>鄂州</city> <city>荆门</city> <city>孝感</city> <city>荆州</city> <city>黄冈</city> <city>咸宁</city> <city>随州</city> <city>恩施</city> <city>神农架</city> </province> <province name="湖南"> <city>长沙</city> <city>株洲</city> <city>湘潭</city> <city>衡阳</city> <city>邵阳</city> <city>岳阳</city> <city>常德</city> <city>张家界</city> <city>益阳</city> <city>郴州</city> <city>永州</city> <city>怀化</city> <city>娄底</city> <city>湘西</city> </province> <province name="广东"> <city>广州</city> <city>韶关</city> <city>深圳</city> <city>珠海</city> <city>汕头</city> <city>佛山</city> <city>江门</city> <city>湛江</city> <city>茂名</city> <city>肇庆</city> <city>惠州</city> <city>梅州</city> <city>汕尾</city> <city>河源</city> <city>阳江</city> <city>清远</city> <city>东莞</city> <city>中山</city> <city>潮州</city> <city>揭阳</city> <city>云浮</city> </province> <province name="广西"> <city>南宁</city> <city>柳州</city> <city>桂林</city> <city>梧州</city> <city>北海</city> <city>防城港</city> <city>钦州</city> <city>贵港</city> <city>玉林</city> <city>百色</city> <city>贺州</city> <city>河池</city> <city>来宾</city> <city>崇左</city> </province> <province name="海南"> <city>海口</city> <city>三亚</city> </province> <province name="重庆"> <city>重庆</city> <city>万州区</city> <city>涪陵区</city> <city>渝中区</city> <city>大渡口区</city> <city>江北区</city> <city>沙坪坝区</city> <city>九龙坡区</city> <city>南岸区</city> <city>北碚区</city> <city>万盛区</city> <city>双桥区</city> <city>渝北区</city> <city>巴南区</city> <city>黔江区</city> <city>长寿区</city> <city>綦江县</city> <city>潼南县</city> <city>铜梁县</city> <city>大足县</city> <city>荣昌县</city> <city>璧山县</city> <city>梁平县</city> <city>城口县</city> <city>丰都县</city> <city>垫江县</city> <city>武隆县</city> <city>忠县</city> <city>开县</city> <city>云阳县</city> <city>奉节县</city> <city>巫山县</city> <city>巫溪县</city> <city>石柱土家族自治县</city> <city>秀山土家族苗族自治县</city> <city>酉阳土家族苗族自治县</city> <city>彭水苗族土家族自治县</city> <city>江津</city> <city>合川</city> <city>永川</city> <city>南川</city> </province> <province name="四川"> <city>成都</city> <city>自贡</city> <city>攀枝花</city> <city>泸州</city> <city>德阳</city> <city>绵阳</city> <city>广元</city> <city>遂宁</city> <city>内江</city> <city>乐山</city> <city>南充</city> <city>眉山</city> <city>宜宾</city> <city>广安</city> <city>达州</city> <city>雅安</city> <city>巴中</city> <city>资阳</city> <city>阿坝</city> <city>甘孜</city> <city>凉山</city> </province> <province name="贵州"> <city>贵阳</city> <city>六盘水</city> <city>遵义</city> <city>安顺</city> <city>铜仁</city> <city>黔西南</city> <city>毕节</city> <city>黔东南</city> <city>黔南</city> </province> <province name="云南"> <city>昆明</city> <city>曲靖</city> <city>玉溪</city> <city>保山</city> <city>昭通</city> <city>丽江</city> <city>思茅</city> <city>临沧</city> <city>楚雄</city> <city>红河</city> <city>文山</city> <city>西双版纳</city> <city>大理</city> <city>德宏</city> <city>怒江</city> <city>迪庆</city> </province> <province name="西藏"> <city>拉萨</city> <city>昌都</city> <city>山南</city> <city>日喀则</city> <city>那曲</city> <city>阿里</city> <city>林芝</city> </province> <province name="陕西"> <city>西安</city> <city>铜川</city> <city>宝鸡</city> <city>咸阳</city> <city>渭南</city> <city>延安</city> <city>汉中</city> <city>榆林</city> <city>安康</city> <city>商洛</city> </province> <province name="甘肃"> <city>兰州</city> <city>嘉峪关</city> <city>金昌</city> <city>白银</city> <city>天水</city> <city>武威</city> <city>张掖</city> <city>平凉</city> <city>酒泉</city> <city>庆阳</city> <city>定西</city> <city>陇南</city> <city>临夏</city> <city>甘南</city> </province> <province name="青海"> <city>西宁</city> <city>海东</city> <city>海北</city> <city>黄南</city> <city>海南</city> <city>果洛</city> <city>玉树</city> <city>海西</city> </province> <province name="宁夏"> <city>银川</city> <city>石嘴山</city> <city>吴忠</city> <city>固原</city> <city>中卫</city> </province> <province name="新疆"> <city>乌鲁木齐</city> <city>克拉玛依</city> <city>吐鲁番</city> <city>哈密</city> <city>昌吉</city> <city>博尔塔拉</city> <city>巴音郭楞</city> <city>阿克苏</city> <city>克孜勒苏</city> <city>喀什</city> <city>和田</city> <city>伊犁</city> <city>塔城</city> <city>阿勒泰</city> <city>石河子</city> <city>阿拉尔</city> <city>图木舒克</city> <city>五家渠</city> </province> <province name="香港"> <city>香港</city> </province> <province name="澳门"> <city>澳门</city> </province> <province name="台湾"> <city>台湾</city> </province> </china>
ProvinceServlet:负责向页面响应所有的省份
package com.xjs.web.servlet; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class ProvinceServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 响应所有省份名称,使用逗号隔开! */ /* * 1.Document对象 * 》创建解析器对象 * 》调用解析器的读方法,传递一个流对象,得到Document */ StringBuilder str=new StringBuilder(); SAXReader reader=new SAXReader(); InputStream in=this.getClass().getResourceAsStream("/china.xml"); Document doc; try { doc = reader.read(in); } catch (DocumentException e) { throw new RuntimeException(e); } Element root = doc.getRootElement();//根节点 Iterator<Element> ele = root.elementIterator(); while(ele.hasNext()){ //每个省份 Element province = ele.next(); //得到省份的名称--即该节点的属性值 String provinceName = province.attributeValue("name"); if(ele.hasNext()){ str=str.append(provinceName+","); }else{ str=str.append(provinceName); } } // System.out.println(str);在控制台显示所有的省份,省份 response.setContentType("text/html;charset=utf-8"); response.getWriter().print(str); } }
北京,天津,河北,山西,内蒙古,辽宁,吉林,黑龙江,上海,江苏,浙江,安徽,福建,江西,山东,河南,湖北,湖南,广东,广西,海南,重庆,四川,贵州,云南,西藏,陕西,甘肃,青海,宁夏,新疆,香港,澳门,台湾
CityServlet:根据选择的省份,去解析XML文件,找到该省的节点,直接使用asXML()转换成字符串,响应给页面
package com.xjs.web.servlet; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class CityServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/xml;charset=utf-8"); request.setCharacterEncoding("utf-8"); /* * 获取省份名称,加载该省对应的<province>元素 * 把元素转换成字符串发送给客户端 */ /* * 1.获取省份的名称 * 2.使用省份名称查找到对应的<province>元素 * 3.把<province>元素转换成字符串,发送! */ SAXReader reader=new SAXReader(); InputStream in=this.getClass().getResourceAsStream("/china.xml"); Document doc; try { doc = reader.read(in); } catch (DocumentException e) { throw new RuntimeException(e); } //获取参数 String pname = request.getParameter("pname"); //根据条件查节点元素 Element proEle=(Element) doc.selectSingleNode("//province[@name='"+pname+"']"); String xmlStr = proEle.asXML();//把元素转换成字符串 // System.out.println(xmlStr);在控制台显示该省中的市(XML格式) response.getWriter().print(xmlStr); } }
<province name="山东"> <city>济南</city> <city>青岛</city> <city>淄博</city> <city>枣庄</city> <city>东营</city> <city>烟台</city> <city>潍坊</city> <city>济宁</city> <city>泰安</city> <city>威海</city> <city>日照</city> <city>莱芜</city> <city>临沂</city> <city>德州</city> <city>聊城</city> <city>滨州</city> <city>荷泽</city> </province>
ajax5.jsp:负责显示页面,处理异步请求
1)请求ProvinceServlet,响应的文本信息,分隔得到数组,然后再添加option元素到select中
2)根据选择的省,去请求CityServlet,响应的是XML信息,直接得到Document对象,然后再去增option元素,
注意:2)中的首先要移除select中的option(除<option>===请选择市===</option>)元素,以免option元素的累加
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'ajax5.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script type="text/javascript"> //创建异步对象 function createXMLHttpRequest() { try { return new XMLHttpRequest(); } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("不晓得你用的什么浏览器!"); throw e; } } } } /* * 1.在文档加载完毕时发送请求,得到所有省份名称,显示在<select name="porvince"/>中 * 2.在选择了新的省份时,发送请求(参数为省份的名称),得到xml文档,即<province>元素 * 3.解析xml文档,得到其中所有的<city>,再得到每个<city>元素的内容,即市名,使用市名生成<option>,插入到<select name="city">元素中 */ window.onload = function() { /* ajax四步,请求ProvinceServlet,得到所有的省份名称 使用每个省份名称创建一个<option>元素,添加到<select name="province">中 */ var xmlHttp = createXMLHttpRequest(); xmlHttp.open("GET", "<c:url value='/ProvinceServlet'/>", true); xmlHttp.send(null); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { var text = xmlHttp.responseText; //使用逗号分隔它,得到数组 var arr = text.split(","); //循环遍历每个省份名称,每个名称生成一个option对象,添加到<select>元素中 for (var i = 0; i < arr.length; i++) { var op = document.createElement("option");//创建指定名称的元素 op.value = arr[i];//设置op的实际值为当前的省份名称 var textNode = document.createTextNode(arr[i]);//创建文本节点 op.appendChild(textNode);//把文本子节点添加到op元素中,指定显示值 document.getElementById("p").appendChild(op); } } }; /* 第二件事情:给<select name="province">添加改变监听器 使用选择的省份名称请求CityServlet,得到<province>元素(xml元素)!!! 获取<province>元素中所有的<city>元素,遍历之,获取每个<city>的文本内容,即市名称 使用每个市名称创建<option>元素添加到<select name="city"> */ var proSelect = document.getElementById("p"); proSelect.onchange = function() { var xmlHttp = createXMLHttpRequest(); xmlHttp.open("POST", "<c:url value='/CityServlet'/>", true); xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlHttp.send("pname=" + proSelect.value);//把下拉列表中选择的值发送给服务器 xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { //把select中的所有option移除(除了请选择) var citySelect=document.getElementById("c"); //获取所有子元素 var optionEleList=citySelect.getElementsByTagName("option"); //循环遍历每个option元素,然后在citySelect中移除 while(optionEleList.length>1){ citySelect.removeChild(optionEleList[1]);//总是删除1下标,因为1删除了,2就变成1了 } var doc = xmlHttp.responseXML; //得到所有名为city的元素 var cityEleList = doc.getElementsByTagName("city"); //循环遍历每个city元素 for (var i = 0; i < cityEleList.length; i++) { var cityEle = cityEleList[i];//得到每个city元素 var cityName; //获取市名称 if (window.addEventListener) { cityName = cityEle.textContent; } else { cityName = cityEle.text;//支持IE } //使用市名称创建option元素,添加到<select name="city"> var op = document.createElement("option"); op.value = cityName; //创建文本节点 var textNode = document.createTextNode(cityName); op.appendChild(textNode); //把op添加到<select>中 citySelect.appendChild(op); } } }; }; }; </script> </head> <body> <h1>省市联动</h1> <select name="porvince" id="p"> <option>===请选择省===</option> </select> <select name="porvince" id="c"> <option>===请选择市===</option> </select> </body> </html>