- AJAX (Asynchronous Javascript And Xml),異步的 js & xml。
- 他能使用 js 訪問服務器,而且是異步訪問。
- 服務器給客戶端的響應一般是整個頁面,一個 html 完整頁面。但在 ajax 中因為是局部刷新,那麼服務器就不用再響應整個頁面。而只是數據。
- text: 純文本
- xml
- json: 他是 js 提供的數據交互額是,他在 ajax 中最受歡迎。
- 同步:
- 發一個請求,就要等待服務器的響應結束,然後才能發第二個請求。
- 刷新的就是整個頁面。
- 異步:
- 發一個請求,無須等待服務器的響應,然後就可以發第二個請求。
- 可以使用 js 接收服務器的響應,然後使用 js 來局部刷新。
優點:
- 異步交互: 增強用戶的體驗。
- 性能: 因為服務器無須再響應整個頁面,只需要響應部分內容,所以服務器的壓力減小。
缺點:
- ajax 不能應用在所有場景
- ajax 無端增多了對服務器的訪問次數,給服務器帶來壓力。
- 第一步(得到 XMLHttpRequest)
-
大多數瀏覽器都支持: var xmlHttp = new XMLHttpRequest(); (IE6.0 以前不支持)
-
編寫創建 XMLHttpRequest 對象的函數
-
- 第二步(打開與服務器的連接)
- xmlHttp.open(): 用來打開與服務器的連接,他需要三個參數。
- 請求方式: 可以是 GET 或 POST
- 請求的URL: 指定服務器端資源,例如: /Java_Web/AServlet
- 請求是否為異步: 如果為 true 表示發送異步請求,否則同步請求。
- xmlHttp.open("GET", "/Java_Web/AServlet", true);
- xmlHttp.open(): 用來打開與服務器的連接,他需要三個參數。
- 第三步(發送請求)
- xmlHttp.send(null): 如果不給可能會造成部分瀏覽器無法發送。
- 參數: 就是請求體內容,如果是 GET 請求,必須給出 null。
- xmlHttp.send(null): 如果不給可能會造成部分瀏覽器無法發送。
- 第四步()
-
在 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.onreadysstatechange = function() { //xmlHttp 的5種狀態都會調用本方法 if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { //雙重判斷: 判斷是否為4狀態,而且還要判斷是否為200 var text = xmlHttp.responseText; } }
-
//web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Java_Web</display-name>
<servlet>
<servlet-name>AServlet</servlet-name>
<servlet-class>pers.servlet.AServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AServlet</servlet-name>
<url-pattern>/AServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
//AServlet.java
package pers.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 ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
return ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
alert("What web explorer you are using?");
throw e;
}
}
}
}
window.onload = function() { //文本加載完畢後執行
var btn = document.getElementById("btn");
btn.onclick = function() { //給按鈕的點擊事件註冊監聽
/*
ajax 四步操作,得到服務器的響應
把響應結果顯示到 h1 元素中
*/
/*
1. 得到異步對象
*/
var xmlHttp = createXMLHttpRequest();
/*
2. 打開與服務器的連接
- 指定請求方式
- 指定請求的 URL
- 指定是否為異步請求
*/
xmlHttp.open("GET", "<c:url value='/AServlet'/>", true);
/*
3. 發送請求
*/
xmlHttp.send(null); //GET 請求沒有請求體,但也要給出 null, 不然 FireFox 可能會不能發送
/*
4. 給異步對象的 onreadystatechange 事件註冊監聽器
*/
xmlHttp.onreadystatechange = function() { //當 xmlHttp 的狀態發生變化時執行
//雙重判斷: xmlHttp 的狀態為4(服務器響應結束), 以及服務器響應的狀態碼為200(響應成功)
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>
- open: xmlHttp.open("POST"..._);
- 添加一步: 設置 Content-Type 請求頭:
- xmlHttp.setRequestHeader("Content-Type", "application/x-www.form-urlencoded");
- send: xmlHttp.send("username=jack870131&password=123"); //發送請求時指定請求體
//web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Java_Web</display-name>
<servlet>
<servlet-name>AServlet</servlet-name>
<servlet-class>pers.servlet.AServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AServlet</servlet-name>
<url-pattern>/AServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
//AServlet.java
package pers.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");
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username"); //獲取請求參數
System.out.println("(POST: ) Hello AJAX" + username);
response.getWriter().print("(POST: ) Hello AJAX" + 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 ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
return ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("What web explorer you are using?");
throw e;
}
}
}
}
window.onload = function() { //文本加載完畢後執行
var btn = document.getElementById("btn");
btn.onclick = function() { //給按鈕的點擊事件註冊監聽
/*
ajax 四步操作,得到服務器的響應
把響應結果顯示到 h1 元素中
*/
/*
1. 得到異步對象
*/
var xmlHttp = createXMLHttpRequest();
/*
2. 打開與服務器的連接
- 指定請求方式
- 指定請求的 URL
- 指定是否為異步請求
*/
//修改 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=jack870131&password=123"); //GET 請求沒有請求體,但也要給出 null, 不然 FireFox 可能會不能發送
/*
4. 給異步對象的 onreadystatechange 事件註冊監聽器
*/
xmlHttp.onreadystatechange = function() { //當 xmlHttp 的狀態發生變化時執行
//雙重判斷: xmlHttp 的狀態為4(服務器響應結束), 以及服務器響應的狀態碼為200(響應成功)
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>
- 編寫頁面:
- ajax3.jsp
- 給出註冊表單頁面
- 給用戶名文本框添加 onblur 事件的監聽
- 獲取文本框的內容,通過 ajax 4步發送給服務器,得到響應結果
- 如果為1: 在文本框後顯示"用戶名已被註冊"
- 如果為0: 什麼都不做
- ajax3.jsp
- 編寫 Servlet
- ValidateUsernameServlet
- 獲取客戶端傳遞的用戶名參數
- 判斷是否為 jack870131
- 是: 返回1
- 否: 返回0
- ValidateUsernameServlet
//web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Java_Web</display-name>
<servlet>
<servlet-name>ValidateUsernameServlet</servlet-name>
<servlet-class>pers.servlet.ValidateUsernameServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ValidateUsernameServlet</servlet-name>
<url-pattern>/ValidateUsernameServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
//ValidateUsernameServlet.java
package pers.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.setCharacterEncoding("text/html;charset=utf-8");
request.setCharacterEncoding("UTF-8");
/*
1. 獲取參數 username
2. 判斷是否為 jack870131
3. 如果是: 響應1
4. 如果不是: 響應0
*/
String username = request.getParameter("username");
if(username.equalsIgnoreCase("jack870131")) {
response.getWriter().print("1");
} else {
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 ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
return ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("What web explorer you are using?");
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. 設置請求頭
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" name="註冊">
</form>
</body>
</html>
- 服務器端:
- 設置響應頭: ContentType, 其值為: text/xml;charset=utf-8
- 客戶端:
- var doc = xmlHttp.responseXML; //得到的是 Document 對象
//web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Java_Web</display-name>
<servlet>
<servlet-name>BServlet</servlet-name>
<servlet-class>pers.servlet.BServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BServlet</servlet-name>
<url-pattern>/BServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
//BServlet.java
package pers.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/html");
String xml = "<students>" +
"<student number='JACK_1001'>" +
"<name>Jack</name>" +
"<age>20</age>" +
"<sex>male</sex>" +
"</student>" +
"</students>";
response.setContentType("text/xml;charset=utf-8");
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 'ajax4.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 ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
return ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("What web explorer you are using?");
throw e;
}
}
}
}
window.onload = function() { //文本加載完畢後執行
var btn = document.getElementById("btn");
btn.onclick = function() { //給按鈕的點擊事件註冊監聽
/*
ajax 四步操作,得到服務器的響應
把響應結果顯示到 h1 元素中
*/
/*
1. 得到異步對象
*/
var xmlHttp = createXMLHttpRequest();
/*
2. 打開與服務器的連接
- 指定請求方式
- 指定請求的 URL
- 指定是否為異步請求
*/
//修改 open 方法,指定請求方式為 POST
xmlHttp.open("GET", "<c:url value='/BServlet'/>", true);
/*
3. 發送請求
*/
xmlHttp.send(null); //GET 請求沒有請求體,但也要給出 null, 不然 FireFox 可能會不能發送
/*
4. 給異步對象的 onreadystatechange 事件註冊監聽器
*/
xmlHttp.onreadystatechange = function() { //當 xmlHttp 的狀態發生變化時執行
//雙重判斷: xmlHttp 的狀態為4(服務器響應結束), 以及服務器響應的狀態碼為200(響應成功)
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;
var age;
var sex;
// 处理浏览器的差异
if (window.addEventListener) {
name = ele.getElementsByTagName("name")[0].textContent; //其他浏览器
} else {
name = ele.getElementsByTagName("name")[0].text; //IE支持
}
if (window.addEventListener) {
age = ele.getElementsByTagName("age")[0].textContent; //其他浏览器
} else {
age = ele.getElementsByTagName("age")[0].text; //IE支持
}
if (window.addEventListener) {
sex = ele.getElementsByTagName("sex")[0].textContent; //其他浏览器
} else {
sex = ele.getElementsByTagName("sex")[0].text; //IE支持
}
var text = number + ", " + name + ", " + age + ", " + sex;
document.getElementById("h1").innerHTML = text;
}
};
};
};
</script>
</head>
<body>
<button id="btn">點擊這裡</button>
<h1 id="h1"></h1>
</body>
</html>
-
頁面
<select name="province"> <option>===請選擇省分===</option> </select> <select name="city"> <option>===請選擇城市===</option> </select>
-
Servlet
- ProvinceServlet: 當頁面加載完畢後馬上請求這個 Servlet
- 他需要加載 China.xml 文件,把所有的省名稱使用字符串發送給客戶端
- ProvinceServlet: 當頁面加載完畢後馬上請求這個 Servlet
-
頁面的工作
- 獲取這個字符串,使用逗號分隔,得到數組
- 循環遍歷每個字符串(省分的名稱),使用每個字符串創建一個 <option> 元素添加到 <select name="province"> 這個元素中
-
CityServlet
- CityServlet: 當頁面選擇某個省時,發送請求。
- 得到省分的名稱: 加載 china.xml 文件,查詢出該省分對應的元素對象,把這個元素換成 xml 字符串,發送給客戶端。
-
頁面的工作
- 把 <select name="city"> 中的所有子元素刪除,但不要刪除===請選擇城市===
- 得到服務器的響應結果: doc。
- 獲取所有的 <city> 子元素,循環遍歷,得到<city> 的內容
- 使用每個 <city> 的內容創建一個<option> 元素,添加到 <select name="city">
//web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Java_Web</display-name>
<servlet>
<servlet-name>ProvinceServlet</servlet-name>
<servlet-class>pers.servlet.ProvinceServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>CityServlet</servlet-name>
<servlet-class>pers.servlet.CityServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ProvinceServlet</servlet-name>
<url-pattern>/ProvinceServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CityServlet</servlet-name>
<url-pattern>/CityServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
//ProvinceServlet.java
package pers.servlet;
import java.io.IOException;
import java.io.InputStream;
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");
/*
* 響應所有省分名稱,使用逗號分隔
*/
/*
* 1. Document 對象 - 創建解析器對象 - 調用解析器的讀方法,傳遞一個流對象,得到Document
*/
try {
SAXReader reader = new SAXReader();
InputStream input = this.getClass().getResourceAsStream("/china.xml");
Document doc = reader.read(input);
/*
* 查詢所有 province 的 name 屬性,得到一堆屬性對象
* 循環遍歷,把所有的屬性值連接成一個字符串,發送給客戶端
*/
List<Attribute> arrList = doc.selectNodes("//province/@name");
StringBuilder sb = new StringBuilder();
for(int i = 0; i < arrList.size(); i++) {
sb.append(arrList.get(i).getValue()); //把每個屬性的值存放到 sb 中
if(i < arrList.size() - 1) {
sb.append(",");
}
}
response.getWriter().print(sb);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
}
//CityServlet.java
package pers.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
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.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"); //注意: 發送 xml 時這裡要修改
/*
* 獲取省分名稱,加載該省對應的 <province> 元素
* 把元素轉換成字符串發送到客戶端
*/
/*
* 1. 獲取省分名稱
* 2. 使用省分名稱查找到對應個<province>元素
* 3. 把<province>元素轉換成字符串,發送
*/
try {
/*
* 得到 Document
*/
SAXReader reader = new SAXReader();
InputStream input = this.getClass().getResourceAsStream("/china.xml");
Document doc = reader.read(input);
/*
* 獲取參數
*/
String pname = request.getParameter("pname"); //獲取省分名稱
Element proEle = (Element) doc.selectSingleNode("//province[@name='" + pname + "']"); //province[@name='北京']
String xmlStr = proEle.asXML(); //把元素轉換成字符串
response.getWriter().print(xmlStr);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
}
//ajax5.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 '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 ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
return ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("What web explorer you are using?");
throw e;
}
}
}
}
/*
* 1. 在文檔加載完畢時,得到所有省分名稱,顯示在<select name="province"/>中
* 2. 在選擇了新的省分時,發送請求(參數為省名稱),得到 xml 文檔,及<province>元素
* 解析xml文檔,得到其中所有的<city>,再得到每個<city>元素的內容,及市名,使用市名生成<option>,差如到<select>元素中
*/
window.onload = function() {
/*
* ajax 四步,請求 ProvinceServlet, 得到所有省分名稱
* 使用每個省份名稱創建一個<option>元素,添加到<servlet 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對象,添加到<servlet>中
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) { //子元素的個數如果大於1就循環,等於1就不循環
citySelect.removeChild(optionEleList[1]); //總是刪除1下標,2就變成1了
}
var doc = xmlHttp.responseXML;
//得到所有名為 city 的元素
var cityEleList = doc.getElementsByTagName("city"); //得到每個 city 元素
//循環遍歷每個 city 元素
for (var i = 0; i < cityEleList.length; i++) {
var cityEle = cityEleList[i]; //支持 FireFox 等瀏覽器
var cityName;
//獲取市名稱
if (window.addEventListener) { //處理瀏覽器的差異
cityName = cityEle.textContent; //支持 FireFox 等瀏覽器
} 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 元素中
//把 op 添加到 <select> 元素中
var citySelect = document.getElementById("c");
citySelect.appendChild(op);
}
}
};
};
};
</script>
</head>
<body>
<h1>省市聯動</h1>
<select name="province" id="p">
<option>===請選擇省分===</option>
</select>
<select name="city" id="c">
<option>===請選擇城市===</option>
</select>
</body>
</html>