1.功能介绍
- ajax.jsp页面
<h1>省市联动</h1>
<select name="province" id="p">
<option>===请选择省===</option>
</select>
<select name="city" id="c">
<option>===请选择市===</option>
</select>
- ProvinceServlet:当页面加载完成后,马上请求这个Servlet!它需要加载china.xml文件,把所有的省的名称使用字符串发送给客户端!
ProvinceServlet.java代码如下:
package cn.itcast.web.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
public class ProvinceServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
try {
// 创建解析器
SAXReader reader = new SAXReader();
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("china.xml");
// InputStream inputStream = this.getClass().getResourceAsStream("/china.xml");
// 得到Document文档
Document doc = reader.read(inputStream);
// xpath查询所有province元素的name属性
List<Attribute> attrList = doc.selectNodes("//province/@name");
StringBuilder sb = new StringBuilder();
// 循环遍历,把所有的name属性值连接成字符串,发送给客户端
for (int x = 0; x < attrList.size(); x++) {
sb.append(attrList.get(x).getValue());
if (x < attrList.size() - 1) {
sb.append(",");
}
}
System.out.println(sb);
response.getWriter().print(sb);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
- ajax.jsp页面的工作:获取这个字符串,使用逗号分隔,得到数组。循环遍历每个字符串(省份的名称),使用每个字符串创建一个<option>元素添加到<select name="province">这个元素中。
// 在文档加载完毕时马上执行
window.onload = function() {
// 得到xmlHttp对象
var xmlHttp = createXMLHttpRequest();
// 调用xmlHttp对象的open()方法,打开与服务器的连接
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 textArr = text.split(",");
// 循环遍历每个省份名称
for ( var x = 0; x < textArr.length; x++) {
var opEle = document.createElement("option");
opEle.value = textArr[x];
// 创建文本节点
var textNode = document.createTextNode(textArr[x]);
opEle.appendChild(textNode);
document.getElementById("p").appendChild(opEle);
}
}
};
};
- CityServlet:当页面选择某个省份时,发送请求!得到省份的名称,加载china.xml文件,查询出该省份对应的元素对象!把这个元素转换成xml字符串,发送给客户端。
CityServlet.java代码如下:
package cn.itcast.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 {
request.setCharacterEncoding("utf-8");
response.setContentType("text/xml;charset=utf-8");
/*
* Document对象的document.asXML()就是将整个文件组成一个String字符串
* Element对象的element.asXML();指的是将这个节点(元素)的开始到结束包含的内容组成String
*/
try {
// 创建解析器
SAXReader reader = new SAXReader();
InputStream inputStream = this.getClass().getClassLoader()
.getResourceAsStream("china.xml");
// 得到Document对象
Document doc = reader.read(inputStream);
// 获取省份名称
String pname = request.getParameter("pname");
// 使用省份名称pname查找对应的<province>元素
Element proEle = (Element) doc.selectSingleNode("//province[@name='" + pname + "']");
// proEle.asXML()指的是将<province>元素的开始到结束的内容组成String字符串
String xmlStr = proEle.asXML();
response.getWriter().print(xmlStr);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
- ajax.jsp页面的工作
* 把<select name="city">中的所有子元素删除,但不要删除<option>===请选择市===</option>
* 得到服务器的响应结果:doc!!!
* 获取所有的<city>子元素,循环遍历,得到<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) {//子元素的个数如果大于1就循环,等于1就不循环了!
citySelect.removeChild(optionEleList[1]);//总是删除1下标,因为1删除了,2就变成1了!
}
var doc = xmlHttp.responseXML;
// 得到所有名为city的元素
var cityEleList = doc.getElementsByTagName("city");
for ( var x = 0; x < cityEleList.length; x++) {
// 得到每个city元素
var cityEle = cityEleList[x];
// 市名称
var cityName;
// 处理浏览器的差异
if (window.addEventListener) {
cityName = cityEle.textContent;
} else {
cityName = cityEle.text;
}
// 创建<option>元素,添加到<select name="city">中
var opEle = document.createElement("option");
opEle.value = cityName;
// 创建文本节点
var textNode = document.createTextNode(cityName);
opEle.appendChild(textNode);
citySelect.appendChild(opEle);
}
}
};
};
2.实现效果如下: