Ajax學習筆記
已完結,請放心食用~
全局刷新和局部刷新
01 全局刷新
整個瀏覽器被新的數據覆蓋,在網絡中傳輸大量的數據,瀏覽器需要加載,渲染頁面
02 局部刷新
在瀏覽器的內部,發起請求,獲取數據,改變頁面中的部分內容
局部刷新的速度更快,可以按需獲取數據
ajax是用來做局部刷新的,局部刷新使用的核心對象是 異步對象(XMLHttpRequest)
這個異步對象是存在瀏覽器內存中的,使用javascript語法創建和使用 XMLHttpRequest 對象
Ajax概念
-
Asynchronous Javascript and XML(異步的 Javascript 和 XML)
- Asynchronous:異步
- 同步只能處理一個請求
- 異步可以分開處理多個請求
- Javascript:Javascript腳本,在瀏覽器中執行
- and:和
- xml:是一種數據格式
- Asynchronous:異步
-
Ajax是一種做局部刷新的新方法(2003年左右),不是一種語言。
-
Ajax包含的技術主要有JavaScript,dom,css,xml等等,核心是JavaScript和xml。
-
JavaScript負責創建異步對象,發送請求,更新頁面的dom對象。
-
Ajax請求需要服務器端的數據。
-
xml:可擴展標記語言
-
網絡中的傳輸的數據格式
-
目前使用 json 替換了 xml
-
<datas> <data1> Car_01 </data1> <data2> Car_02 </data2> <data3> Car_03 </data3> <data4> Car_04 </data4> </datas>
-
-
Ajax異步實現步驟
ajax中使用XMLHttpRequest對象
step 01 創建異步對象
var xmlHttp = new XMLHttpRequest();
step 02 給異步對象綁定事件
-
給異步對象綁定onreadstatechange事件,獲知請求的狀態的變化
-
onreadystatechange事件
- 當請求被發送到服務器時,我們需要執行一些基於響應的任務
- 當異步對象發起請求,獲取了數據,都會觸發這個事件
- 每當 readyState 改變時,就會觸發 onreadystateChange 事件
-
這個事件需要指定一個函數,在函數中處理狀態的變化
- 此事件可以指定一個處理函數function
-
bth.onclick = fun1(); // 點擊這個按鈕會觸發fun1函數 function fun1(){ alert("按鈕單擊"); } // For example, xmlHttp.onreadystatechange = function(){ // 用匿名函數直接指定 // 處理請求的狀態變化 if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ){ // 數據已經返回來准備好了 && 網絡請求是成功的 // 可以處理服務器端的數據,更新當前頁面 var data = xmlHttp.responseText; // 獲取服務器返回的數據,使用異步對象的屬性 responseText document.getElementById("name").value = data; } }
-
XMLHttpRequest對象的三個重要的屬性
-
onreadystatechange 屬性
- 一個js函數名 或 直接定義函數,每當readyState屬性改變時,就會調用該函數
-
readyState 屬性:存有 XMLHttprequest 的狀態,表示異步對象請求從0到4的狀態變化
-
readyState == 0:請求未初始化,創建異步請求對象,var xmlHttp = new XMLHttpReaquest()
-
readyState == 1:初始化異步請求對象,xmlHttp.open( 請求方式,請求地址,true ) 。
-
readyState == 2:異步對象發送請求,xmlHttp.send() 。
-
readyState == 3:異步對象接收應答數據,從服務端返回數據,XMLHttpRequest 內部處理。
- 從服務器端獲取了原始數據
- 此時3是異步對象內部使用,開發人員一般不用。
-
readyState == 4:異步請求對象已經將數據解析完畢,此時才可以讀取數據。
- 異步對象把接受的數據處理完成(數據是已經處理好的)。
- 此時開發人員在4的時候處理數據。
- 在 4 的時候,開發人員做什么?——> 更新當前頁面。
-
-
state 屬性:表示網絡請求的狀況
- 當 status == 200 時,表示網絡請求是成功的
- 當 status == 404 時
- 當 status == 500 時
-
step 03 初始異步請求對象
-
異步的方法 open()
-
xmlHttp.open(請求方式get|post,"服務端的訪問地址",同步|異步請求)
-
同步|異步請求:默認為true,表示異步請求
-
xmlHttp.open("get","loginServlet?name=zhangsan&pwd=123",true);
-
step 04 使用異步對象發送請求
- xmlHttp.send()
step 補充說明
-
獲取服務器返回的數據,使用異步對象的屬性 responseText
- 使用例子:xmlHttp.reponseText
-
使用需要配合服務器端,因為需要到服務端拿數據,單獨使用沒有意義
-
回調:當請求的狀態變化時,異步對象會自動調用 onreadystatechange事件 對應的函數
- 完成整個流程,異步對象內部會多次調用這個函數
Ajax舉例:計算BMI
BMI簡介
- 需求
- 計算某個用戶的BMI,用戶在jsp輸入自己的身高,體重
- servlet中計算BMI,並顯示BMI的計算結果和建議
- BMI指數
- 身體質量指數(BodyMassindex)
- 體重公斤數除以身高米數平方得出的數字
- 目前國際上常用的衡量人體胖瘦程度以及是否健康的一個標准
- 成人的 BMI 數值
- 過輕:低於18.5
- 正常:18.5 ~ 23.9
- 過重:24 ~ 27
- 肥胖:28 ~32
- 非常肥胖:高於32
全局刷新方式
step 01 創建新項目
- idea創建新項目
- 創建空白項目,name自定義
- 右鍵項目文件夾,Add Framework Support...
- 選擇 Java EE \ Web Application(默認version 4.0,勾選Create web.xml)
step 02 查看目錄結構
- src
- web
- WEB-INF \ web.xml
- index.jsp
- project_name.imi
step 03 編寫服務器頁面
-
第一步:打開 index.jsp 頁面
- 打開 web \ index.jsp 文件,設計頁面布局
- 標題 title 標簽自定義
- 提示文字 p 標簽自定義
- form表單用來提交數據
- 需要的參數:姓名、體重、身高
-
第二步:准備服務器端
- (1)創建 Servlet
- Package:com.XXX.controller
- 不勾選其他項
- (2)設置 tomcat
-
-
-
-
- 最后打開 tomcat \ bin \ tomcat.exe 啟動服務
- 不然會出大問題!(tomcat服務更新異常,無法更新或更新不完全)
-
- (3)創建 jsp 結果頁面
- web 目錄下創建 jsp 頁面,以便實現 index.jsp(首頁)到 result.jsp 的跳轉
- (1)創建 Servlet
-
第三步:編寫服務器端
-
(1)編寫 web.xml
-
標簽對 -
xml文件中給出了 servlet 標簽對 的內容
-
<servlet> <servlet-name>Servlet模塊名</servlet-name> <servlet-class>com.XXX.controller(包名).Servlet模塊名</servlet-class> </servlet>
-
-
標簽對 -
編寫 servlet-mapping 標簽對 的內容
-
<servlet-mapping> <servlet-name>Servlet模塊名</servlet-name> <url-pattern>/路徑訪問地址</url-pattern> </servlet-mapping>
-
注意,若url路徑落下 ” / “ ,啟動 tomcat 會出現下圖描述的報錯
-
-
-
-
(2)編寫 myServlet.java 類
-
src \ com.XXX.controller \ myServlet.java
-
在doGet()方法中編寫程序
-
// 接收參數 String strname = request.getParameter("name"); String height = request.getParameter("height"); String weight = request.getParameter("weight");
-
// 計算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 = "您的身材是正常的"; }else if ( bmi > 24 && bmi <27){ msg = "您的身材較胖"; }else { msg = "您的身材過胖"; } System.out.println("msg="+msg); msg = "您好," + strName + "先生/女士,您的BMI指數為:" + bmi + "," + msg;
-
// 把數據存入到request request.setAttribute("msg",msg);
-
// 轉發到新的頁面 request.getRequestDispatcher("/result.jsp").forward(request,response);
-
-
(3)編寫 result.jsp 頁面
-
web \ result.jsp
-
<title>結果頁面</title> <p>顯示BMI計算結果</p> <h3>${msg}</h3>
-
-
-
第四步:運行tomcat,訪問8080端口
step 補充說明
-
改寫 myServlet.java 類
-
更改其中數據輸出方式(使用應答對象輸出數據)
-
/* // 把數據存入到request request.setAttribute("msg",msg); // 轉發到新的頁面 request.getRequestDispatcher("/result.jsp").forward(request,response); */
-
// 使用HttpServletResponse輸出數據 response.setContentType("text/html;charset=utf-8"); // 獲取PrintWriter PrintWriter pw = response.getWriter(); // 輸出數據 pw.println(msg); // 清空緩存 pw.flush(); // 關閉close pw.close();
-
成功運行!
-
局部刷新方式
概述
使用ajax的局部刷新
1.新建jsp,使用XMLHttpRequest異步對象。
使用異步對象有四個步驟:
1.創建
2.綁定事件
3.初始請求
4.發送請求
2.創建服務器的servlet,接收並處理數據,把數據輸出給異步對象。
step 01 創建新項目 / 新模塊
- 創建新項目同全局刷新方式
- 創建新模塊,注意為了方便區分可以把根目錄設為和原模塊(項目)同級
step 02 查看目錄結構
- 查看目錄結構同全局刷新方式
step 03 編寫服務器頁面
-
第一步:打開 index.jsp 頁面
-
打開 web \ index.jsp 文件,設計頁面布局
-
標題 title 標簽自定義
-
提示文字 p 標簽自定義
-
div 標簽圈定范圍
-
input 標簽設置id,以便后續...
-
input 標簽設置 onclick 觸發 doAjax() 函數
-
注意,Ajax的數據傳輸不是通過form表單提交的
-
<!-- 寫在head中 --> <script type="text/javascript"> // 使用內存中的異步對象,代替瀏覽器發起請求。異步對象是使用js創建和管理的。 function doAjax(){ // 1.創建異步對象 var xmlHttp = new XMLHttpRequest(); // 2.綁定事件 xmlHttp.onreadystatechange = function (){ // 處理服務器端返回的數據,更新當前頁面 // alert("readyState屬性值====" + xmlHttp.readyState + " | status:" + xmlHttp.status); if( xmlHttp.readyState == 4 && xmlHttp.status==200 ){ alert(xmlHttp.responseText); } } // 3.初始請求數據 xmlHttp.open("get","bmiAjax",true); // 4.發起請求 xmlHttp.send(); } </script>
-
-
第二步:准備服務器端
- (1)創建 Servlet
- (2)設置 tomcat
- 補充:如果是子模塊使用同項目配置好的tomcat,只需要設置:
-
-
第三步:編寫服務器端
-
(1)編寫 web.xml
-
<servlet> <servlet-name>MyBmiAjaxServlet</servlet-name> <servlet-class>com.ding.controller.MyBmiAjaxServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyBmiAjaxServlet</servlet-name> <url-pattern>/myBmiAjaxServlet</url-pattern> </servlet-mapping>
-
-
(2)編寫 myServlet.java 類
-
@WebServlet(name = "MyBmiAjaxServlet", value = "/MyBmiAjaxServlet") public class MyBmiAjaxServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("接受了Ajax的請求"); // 接收參數 String strName = request.getParameter("name"); String weight = request.getParameter("weight"); String height = request.getParameter("height"); // 計算BMI float h = Float.valueOf(height); float w = Float.valueOf(weight); float bmi = w / ( h * h ); String msg; // 判斷bmi的范圍 if ( bmi < 18.5 ){ msg = "您的身材較瘦"; }else if ( bmi >= 18.5 && bmi <= 23.9 ){ msg = "您的身材是正常的"; }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(); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
-
-
編寫 index.jsp 頁面
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>我的局部刷新測試-Ajax練習</title> <script type="text/javascript"> // 使用內存中的異步對象,代替瀏覽器發起請求。異步對象是使用js創建和管理的。 function doAjax(){ // 1.創建異步對象 var xmlHttp = new XMLHttpRequest(); // 2.綁定事件 xmlHttp.onreadystatechange = function (){ // 處理服務器端返回的數據,更新當前頁面 if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ) { var data = xmlHttp.responseText; // 更新dom對象,更新頁面數據 document.getElementById("mydata").innerText = data; } } // 3.初始請求數據 // 獲取dom對象的value屬性值 var name = document.getElementById("name").value; var weight = document.getElementById("weight").value; var height = document.getElementById("height").value; // bmiPrintServlet?name=張三&weight=100&height=1.85 var param = "name=" + name + "&weight=" + weight + "&height=" + height; xmlHttp.open("get","myBmiAjaxServlet?" + param,true); // 4.發起請求 xmlHttp.send(); } </script> </head> <body> <p>局部刷新-Ajax-計算BMI</p> <div> 姓名:<input type="text" id="name"/><br/> 體重(公斤):<input type="text" id="weight"/><br/> 身高(米):<input type="text" id="height"/><br/> <input type="button" value="計算BMI" onclick="doAjax()"> <br/> <br/> <div id = "mydata"> 等待加載數據...... </div> </div> </body> </html>
-
-
局部刷新方式原理初探
從全局刷新到局部刷新
step 01 創建新項目 / 新模塊
step 02 查看目錄結構
step 03 編寫服務器頁面
-
第一步:打開 index.jsp 頁面
-
第二步:准備服務器端
-
【上述三大步二小步同局部刷新方式步驟內容】
-
第三步:編寫服務器端
-
重寫服務器端 Version 1.0
-
目的:驗證異步對象是否可以發起請求
-
更改對象:myServlet.java
-
// 以下內容均寫在doGet()方法中 System.out.println("接受了Ajax的請求");
-
如果這句話可以輸出(控制台可以顯示),說明請求發起成功
-
web.xml設置路徑
-
啟動 tomcat,服務成功發布
-
證明異步對象確實可以發起請求啦
-
// 異步對象在發起請求的過程中是有狀態變化的(5種狀態)
-
-
重寫服務器端 Version 2.0
-
目的:觀察異步對象發起請求過程中的狀態變化
-
更改對象:index.jsp
-
<!-- 寫在head中 --> <script type="text/javascript"> // 使用內存中的異步對象,代替瀏覽器發起請求。異步對象是使用js創建和管理的。 function doAjax(){ // 1.創建異步對象 var xmlHttp = new XMLHttpRequest(); // 2.綁定事件 xmlHttp.onreadystatechange = function (){ // 處理服務器端返回的數據,更新當前頁面 alert("readyState屬 性值====" + xmlHttp.readyState); } // 3.初始請求數據 xmlHttp.open("get","bmiAjax",true); // 4.發起請求 xmlHttp.send(); } </script>
-
-
-
-
-
服務器端是空數據,但整個流程步驟完成執行,所以狀態碼變化為 0 => 1 => 2 => 4(0看不到)
-
-
重寫服務器端 Version 3.0
-
在 index.jsp 加上狀態碼,觀察其變化
-
// 2.綁定事件 xmlHttp.onreadystatechange = function (){ // 處理服務器端返回的數據,更新當前頁面 alert("readyState屬性值====" + xmlHttp.readyState + " | status:" + xmlHttp.status); }
-
-
-
-
-
-
重寫服務器端 Version 4.0
-
目的:觀察異步對象發起請求過程中完整的狀態變化
-
更改對象:myServlet.java
-
// 寫在doGet()方法中 System.out.println("接受了Ajax的請求"); PrintWriter pw = response.getWriter(); pw.println("Hello,Ajax!"); pw.flush(); pw.close();
-
-
-
-
-
-
重寫服務器端 Version 5.0
-
目的:觀察異步對象發起請求過程中完整的狀態變化
-
更改對象:index.jsp
-
// 2.綁定事件 xmlHttp.onreadystatechange = function (){ // 處理服務器端返回的數據,更新當前頁面 if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ){ alert(xmlHttp.responseText); } }
-
-
點擊按鈕彈窗后,數據並未發生變化
-
- 按鈕中有一個異步對象xmlHttp,該異步對象發起請求
- 把數據給Servlet,Servlet又把數據給了異步對象xmlHttp
-
-
-
重寫服務器端 Version 5.0
-
傳參
-
怎么獲取身高、體重、姓名的數據呢? ==> dom對象的值
-
更改對象:index.jsp
-
訪問地址:使用get方式傳遞參數
http://localhost:8080/Ajax_Dongli_war_exploded/bmiPrintServlet?name=張三&weight=100&height=1.85 -
// 3.初始請求數據 // 獲取dom對象的value屬性值 var name = document.getElementById("name").value; var weight = document.getElementById("weight").value; var height = document.getElementById("height").value; // bmiPrintServlet?name=張三&weight=100&height=1.85 var param = "name=" + name + "&weight=" + weight + "&height=" + height; alert("param=" + param); xmlHttp.open("get","bmiAjax?" + param,true);
-
-
-
重寫服務器端 Version 5.1
-
收參
-
更改對象:myServlet.java
-
// 寫在doGet()方法中 System.out.println("接受了Ajax的請求"); // 接收參數 String strName = request.getParameter("name"); String weight = request.getParameter("weight"); String height = request.getParameter("height"); // 計算BMI float h = Float.valueOf(height); float w = Float.valueOf(weight); float bmi = w / ( h * h ); String msg; // 判斷bmi的范圍 if ( bmi < 18.5 ){ msg = "您的身材較瘦"; }else if ( bmi >= 18.5 && bmi <= 23.9 ){ msg = "您的身材是正常的"; }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();
-
-
-
重寫服務器端 Version 5.2
-
拿到數據之后如何更新頁面?
-
更改頁面:index.jsp
-
<!-- 在jsp頁面body標簽的div標簽內添加如下代碼 --> <br/> <br/> <div id = "mydata">等待加載數據......</div>
-
// 在jsp頁面head標簽的script標簽內修改如下代碼 // 2.綁定事件 xmlHttp.onreadystatechange = function (){ // 處理服務器端返回的數據,更新當前頁面 if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ){ // alert(xmlHttp.responseText); var data = xmlHttp.responseText; // 更新dom對象,更新頁面數據 document.getElementById("mydata").innerText = data; } }
-
將關於彈窗提示的測試代碼注釋掉
-
-
Ajax舉例:根據省份id查詢省份名稱
查詢概述
-
需求:用戶在文本框架輸入省份的編號id,在其他文本框顯示省份名稱
-
項目環境准備
-
數據庫:springdb
-
數據表
-
省份信息表
-
SET FOREIGN_KEY_CHECKS=0 ; DROP TABLE IF EXISTS `pro`; CREATE TABLE `pro`( `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 `pro` VALUES ('1','河北','冀','石家庄'); INSERT INTO `pro` VALUES ('2','山西','晉','太原市'); INSERT INTO `pro` VALUES ('3','內蒙古','蒙','呼和浩特市'); INSERT INTO `pro` VALUES ('4','遼寧','遼','沈陽'); INSERT INTO `pro` VALUES ('5','江蘇','蘇','南京'); INSERT INTO `pro` VALUES ('6','浙江','浙','杭州'); INSERT INTO `pro` VALUES ('7','安徽','皖','合肥'); INSERT INTO `pro` VALUES ('8','福建','閩','福州'); INSERT INTO `pro` 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') ;
-
-
-
局部刷新方式
step 01 創建新項目
- 創建空白項目
- 右鍵點擊添加框架支持(Add Framework Support...)
- 選擇 Java EE \ Web Application
- 在 web \ WEB-INF 下新建 classes 和 libs 文件夾
- 在項目結構(Project structs)下設置自定義編譯輸出路徑為新建的classes文件夾
- 在項目結構(Project structs)下設置 tomcat 依賴和檢查 factes 的 sources root 是否勾選
- src 右鍵創建新的Servlet模塊
step 02 准備連接數據庫
- jar包准備
- 將項目所需要的jar包cv到 web \ WEB-INF 下新建的 libs 文件夾中
- 前綴 jackson 的 jar包是做 json 用到的,mysql...是mysql連接數據庫的驅動
- 將 jar 包加入到項目中,讓項目可以識別 jar 包
- Project Structs ——> 選中項目 ——> modules ——> depenencies ——> 添加四個 jar 包
- Project Structs ——> Problems ——> 每個問題右鍵點擊添加 jar 包
step 03 搭建頁面結構
-
編寫 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>QueryInfoServlet</servlet-name> <servlet-class>com.ding.controller.QueryInfoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>QueryInfoServlet</servlet-name> <url-pattern>/queryInfoServlet</url-pattern> </servlet-mapping> </web-app>
-
-
編寫 index.jsp
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Ajax根據省份id獲取名稱</title> <script type="text/javascript"> function search(){ // 發起Ajax請求,傳遞參數給服務器,服務器返回數據 // 1.創建異步對象 var xmlHttp = new XMLHttpRequest(); // 2.綁定事件 xmlHttp.onreadystatechange = function(){ if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ){ var data = xmlHttp.responseText; // 更新dom對象,更新頁面數據 document.getElementById("proname").value = xmlHttp.responseText; } } // 3.初始異步對象 // 獲取proid文本框的值 var proid = document.getElementById("proid").value; xmlHttp.open("get","queryInfoServlet?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"></td> </tr> </table> </body> </html>
-
-
編寫 Dao層
-
package com.ding.dao; 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?serverTimezone=UTC"; String username = "root"; String password = "123456"; String name = ""; // 加載驅動 try { Class.forName("com.mysql.cj.jdbc.Driver"); conn = DriverManager.getConnection(url,username,password); // 創建prepareStatement sql = "select name from pro where id=?"; pst = conn.prepareStatement(sql); // 設置參數值 pst.setInt(1,provinceId); // 執行sql rs = pst.executeQuery(); // 遍歷rs // while(rs.next()){ // 當你的rs中有多於一條記錄時 // name = rs.getString("name"); // } if(rs.next()){ // 因為記錄集就一行 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; } }
-
-
編寫 myServlet.java 類
-
package com.ding.controller; import com.ding.dao.ProvinceDao; import jakarta.servlet.*; import jakarta.servlet.http.*; import jakarta.servlet.annotation.*; import java.io.IOException; import java.io.PrintWriter; @WebServlet(name = "QueryInfoServlet", value = "/queryInfoServlet") public class QueryInfoServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 處理get請求 System.out.println("響應了Ajax請求"); String strProid = request.getParameter("proid"); System.out.println("strProid"); String name = "默認是無數據"; // 訪問dao,查詢數據庫 if(strProid != null){ // 創建dao對象,調用它的方法 ProvinceDao dao = new ProvinceDao(); name = dao.queryProvinceNameById(Integer.valueOf(strProid)); } // 使用HttpServletResponse輸出數據 response.setContentType("text/html;charset=utf-8"); PrintWriter pw = response.getWriter(); // pw.println("中國"); pw.println(name); pw.flush(); pw.close(); } }
-
JSON
什么是 Json
如果我們從服務器端返回的數據不是一個而是多個
比如從服務器端返回的數據包括省會的名稱、簡稱等,此時返回文本框內的值就不方便了
所以這里使用json數據交換格式。
Ajax發起請求 ——> Servlet
Servlet返回的一個Json格式的字符串
( 字符串中有多個數據,包括名稱、簡稱等 { name:"河北" , jiancheng:"冀","shenghui:"石家庄" } )
json分類
01 json對象
JSONObject,這種對象的格式是 名稱:值 (所謂的“名稱-值對”),也可以看作是 key : value 格式
{名稱 : 值} 或者說 { key : value }
02 json數組
JSONArray,基本格式 [ { name:"河北" , jiancheng:"冀","shenghui:"石家庄" } , {name:"山西" , jiancheng:"晉","shenghui:"太原"} ]
[ { name:"河北" , jiancheng:"冀","shenghui:"石家庄" } , {name:"山西" , jiancheng:"晉","shenghui:"太原"} ]
Why Json?
01 json格式理解簡單,含義清晰
02 json格式數據在多種語言中比較容易處理。使用java、js等讀寫json格式的數據比較容易
03 json格式數據占用的空間小,在網絡中傳輸的速度快,用戶的體驗好
Jackson工具庫
Java中處理json的工具庫:gson,fastjson,jackson,json-lib
在程序中如何處理json?
使用jackson工具庫,把一個java對象轉為一個json格式的字符串
Aajx+JSON舉例:根據省份id查詢省份名稱
// 那么需要有一個java對象
// 創建數據表對應的實體類
局部刷新方式
概述
使用ajax的局部刷新
1.新建jsp,使用XMLHttpRequest異步對象。
使用異步對象有四個步驟:
1.創建
2.綁定事件
3.初始請求
4.發送請求
2.創建服務器的servlet,接收並處理數據,把數據輸出給異步對象。
step 01 創建新項目 / 新模塊
- 創建新項目同全局刷新方式
- 創建新模塊,注意為了方便區分可以把根目錄設為和原模塊(項目)同級
step 02 查看目錄結構
- 查看目錄結構同全局刷新方式
step 03 編寫服務器頁面
-
第一步:打開 index.jsp 頁面
-
創建使用 json 的頁面
-
打開 web \ index.jsp 文件,設計頁面布局
-
標題 title 標簽自定義
-
提示文字 p 標簽自定義
-
div 標簽圈定范圍
-
input 標簽設置id,以便后續...
-
input 標簽設置 onclick 觸發 doAjax() 函數
-
注意,Ajax的數據傳輸不是通過form表單提交的
-
輸入一個省份的編號,有很多數據信息返回,更新dom頁面
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>使用json格式的數據</title> </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>
-
-
第二步:准備服務器端
- (1)創建 Servlet
- (2)設置 tomcat
- 補充:如果是子模塊使用同項目配置好的tomcat,只需要設置:
-
-
第三步:編寫服務器端
-
搭建服務器端的基本結構
- com \ ding \ controller \ QueryInfoServlet.java
- com \ ding \ dao\ ProvinceDao.java
- com \ ding \ entity \ Province.java
-
(1)編寫 web.xml
-
<servlet> <servlet-name>QueryInfoServlet</servlet-name> <servlet-class>com.ding.controller.QueryInfoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>QueryInfoServlet</servlet-name> <url-pattern>/queryInfoServlet</url-pattern> </servlet-mapping>
-
-
(2)編寫entity層 Province.java
-
package com.ding.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; } }
-
-
(3)編寫 dao層 ProvinceDao.java
-
dao層返回一個province對象
-
package com.ding.dao; import com.ding.entity.Province; 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?serverTimezone=UTC"; String username = "root"; String password = "123456"; String name = ""; // 加載驅動 try { Class.forName("com.mysql.cj.jdbc.Driver"); conn = DriverManager.getConnection(url,username,password); // 創建prepareStatement sql = "select name from pro where id=?"; pst = conn.prepareStatement(sql); // 設置參數值 pst.setInt(1,provinceId); // 執行sql rs = pst.executeQuery(); // 遍歷rs // while(rs.next()){ // 當你的rs中有多於一條記錄時 // name = rs.getString("name"); // } if(rs.next()){ // 因為記錄集就一行 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; } // 根據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?serverTimezone=UTC"; String username = "root"; String password = "123456"; Province province = null; // 加載驅動 try { Class.forName("com.mysql.cj.jdbc.Driver"); conn = DriverManager.getConnection(url,username,password); // 創建prepareStatement 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中有多於一條記錄時 // name = rs.getString("name"); // } if(rs.next()){ 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; } }
-
-
(4)編寫 myServlet.java 類
-
package com.ding.dao; import com.ding.entity.Province; 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?serverTimezone=UTC"; String username = "root"; String password = "123456"; String name = ""; // 加載驅動 try { Class.forName("com.mysql.cj.jdbc.Driver"); conn = DriverManager.getConnection(url,username,password); // 創建prepareStatement sql = "select name from pro where id=?"; pst = conn.prepareStatement(sql); // 設置參數值 pst.setInt(1,provinceId); // 執行sql rs = pst.executeQuery(); // 遍歷rs // while(rs.next()){ // 當你的rs中有多於一條記錄時 // name = rs.getString("name"); // } if(rs.next()){ // 因為記錄集就一行 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; } // 根據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?serverTimezone=UTC"; String username = "root"; String password = "123456"; Province province = null; // 加載驅動 try { Class.forName("com.mysql.cj.jdbc.Driver"); conn = DriverManager.getConnection(url,username,password); // 創建prepareStatement 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中有多於一條記錄時 // name = rs.getString("name"); // } if(rs.next()){ 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; } }
-
寫完servlet,還沒寫ajax的請求呢,先測試一下servlet能不能用(可不可以正常返回數據)
-
serlvet寫完之后測一下
-
-
-
編寫 index.jsp 頁面
-
在js中,可以將json格式的字符串,轉為json對象,json中的key,就是json對象的屬性名
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>使用json格式的數據</title> <script type="text/javascript"> function doSearch(){ // 1.創建異步對象 var xmlHttp = new XMLHttpRequest(); // 2.綁定事件 xmlHttp.onreadystatechange = function (){ if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ){ var data = xmlHttp.responseText; var jsonobj = eval("(" + data + ")"); // eval是執行括號中的代碼,把json字符串轉為json對象 // 更新dom對象 document.getElementById("proname").value = jsonobj.name; document.getElementById("projiancheng").value = jsonobj.jiancheng; document.getElementById("proshenghui").value = jsonobj.shenghui; } } // 3. 初始異步對象的數據 var proid = document.getElementById("proid").value; xmlHttp.open("get","queryInfoServlet?proid=" + proid,true); // 4.發起請求 xmlHttp.send(); } </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>
-
-
同步和異步
open函數第三個參數的作用(true)
同步還是異步?——> 真表示異步,假表示同步;
true:異步處理請求,使用異步對象發起請求后,不用等待數據處理完畢就可以執行其他的操作
按理說,發送到servlet的數據,返回后才可以繼續使用,但異步可以同時處理多個請求
不會妨礙其他代碼的執行
同步的方式,在任意時刻只能執行一個請求