Java Web - Ajax技术
一 為什么會有Ajax技術的出現
想必大家肯定用過百度,當我們在百度的搜索框中輸入文字的時候,下面就會自動出現你可能希望搜索的內容,但是頁面中的其他內容都沒有變化:
可以想象,這些內容都是根據在輸入框中輸入的內容動態變化的,而不是最開始就響應到瀏覽器中的,否則互聯網中那么多內容,這個響應內容得有多大。我們也可以F12打開瀏覽器的調試模式,可以看到當你在輸入框中每輸入一個字符,就會有一個響應。
你可以想象如果現在沒有Ajax技術,你會怎么做呢?我想,這也許是一個解決的辦法:
之后每次響應的內容都重新和第一次響應的內容拼接起來,再次響應界面,從而刷新整個界面,但只有搜索框中的內容改變,而其他內容不變;但是這將導致一個問題,那就是重復的內容總是一遍又一遍的發送,這真的有必要嗎?這也就是Ajax技術誕生的原因。
二 什么是Ajax技術
這里引用了百度百科的內容:
https://baike.baidu.com/item/ajax/8425?fr=aladdin
- Ajax 即“Asynchronous Javascript And XML”(異步 JavaScript 和 XML),是指一種創建交互式網頁應用的網頁開發技術。
- Ajax = 異步 JavaScript 和 XML 或者是 HTML(標準通用標記語言的子集)。
- Ajax 是一種用于創建快速動態網頁的技術。
- Ajax 是一種在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。
通過在后臺與服務器進行少量數據交換,Ajax 可以使網頁實現異步更新。這意味著可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。傳統的網頁(不使用 Ajax)如果需要更新內容,必須重載整個網頁頁面。Ajax 在瀏覽器與 Web 服務器之間使用異步數據傳輸(HTTP 請求),這樣就可使網頁從服務器請求少量的信息,而不是整個頁面。
使用 JavaScript 向服務器提出請求并處理響應而不阻塞用戶核心對象XMLHttpRequest。通過這個對象,您的 JavaScript 可在不重載頁面的情況與 Web 服務器交換數據,即在不需要刷新頁面的情況下,就可以產生局部刷新的效果。
對于開發人員而言,知道以上這么多就可以了,相信有了上面的描述,你對Ajax技術已經有的一定的認識,下面我們將在實例中講解如何使用Ajax技術。
三 Ajax技術的使用
3.1 第一個Ajax程序
下面給出一個演示的例子:
mainPage.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %> <%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %><!doctype html> <html lang="ch"><head><base href="<%=basePath%>"><title>mainPage</title><script type="text/javascript">function getDate() {//創建Ajax引擎對象var ajax;ajax = new XMLHttpRequest();//復寫onreadystatement函數ajax.onreadystatechange = function () {//獲取響應內容,響應到方框內var result = ajax.responseText;var showdiv = document.getElementById("showdiv");showdiv.innerHTML = result;}//發送請求ajax.open("get", "ajaxtest");ajax.send(null);}</script><style type="text/css">#showdiv{border: solid 1px;width: 200px;height: 100px;}</style></head><body><input type="button" value="test" onclick="getDate()"><div id="showdiv"></div></body> </html>AjaxServlet.java
package com.chester.web.servlet;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException;@WebServlet("/ajaxtest") public class AjaxServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");resp.getWriter().write("good job!!");} }啟動服務器,在瀏覽器中訪問mainPage.jsp文件,結果如下:
當我們點擊test按鈕,結果如下:
我們主要關注mainPage.jsp文件中JS腳本中的內容:
<script type="text/javascript">function getDate() {//創建Ajax引擎對象var ajax;ajax = new XMLHttpRequest();//復寫onreadystatement函數ajax.onreadystatechange = function () {//獲取響應內容,響應到方框內var result = ajax.responseText;var showdiv = document.getElementById("showdiv");showdiv.innerHTML = result;}//發送請求ajax.open("get", "ajaxtest");ajax.send(null);} </script>可以看到使用ajax的步驟如下
- 創建Ajax引擎對象
- 復寫onreadystatechange函數
- 發送請求
創建引擎對象很簡單,關于發送請求實際上和瀏覽器在地址欄發送是一個道理,這里open函數中寫的參數是請求方式和請求地址。請求方式為get所以send的內容為null,如果請求方式為post,我們就需要在send中寫入請求內容了(具體可以看下面的 五 Ajax的請求方式),下面著重講解onreadystatechange函數。
onreadystatechange函數,從字面意思理解的話就是當readystate改變的時候;改變的時候,干什么呢?是執行。它實際上在上面只是聲明重寫了一下,我們沒有直接調用這個函數,它是被調用的,聲明一般而言我們都寫的比較靠前,這也就是為什么函數的重寫在發送請求之前。
關于readyState,它實際上是Ajax的一個狀態,它有5個狀態,每次改變的時候onreadystatechange函數就執行一次:
所以按下test按鈕的時候,onreadystatechange應該執行了四次,那么我們知道只有當表示數據成功接收的時候我們才有執行的必要(對這里的上下文而言是這樣的,你可以根據具體的情況做出改變,比如寫一些測試代碼),所以上面的JS腳本這樣寫更加合理:
那么請求是否每次都會成功呢?不成功的話,難道我們要這樣顯示嗎?
這顯然是不合理的,至少我們應該給用戶一些提示,所以我們的JS腳本又改成這樣;
其中ajax.status存儲的是每次請求的狀態碼。
上面的內容就構成了一個基本的Ajax的應用。
四 Ajax例子的代碼優化
4.1 Ajax的同步與異步
我們應該意識到這樣一個問題:當發送請求后,我們是阻塞在send函數處,等待響應的到來從而執行onreadystatechange函數,還是執行完send函數之后,直接執行函數中接下來的內容,當響應到來再執行onreadystatechange函數;等待就是同步,直接執行下面的內容就是異步。
默認我們是使用異步的方式,在我們的open函數中,有這樣一個參數選項,比如我們改成同步的方式:
ajax.open("get", "ajaxtest", false);同步的方式在實際使用中還是比較少的。
4.2 未及時響應時的處理
在上面的情況中,如果我們點擊test按鈕,而服務器未及時響應(比如在AjaxServlet.java中寫Thread.sleep(3000);),我們希望可以給用戶一些提示,而不是保持原有的空白框,這很簡單,我們只需要這樣修改js代碼:
<script type="text/javascript">function getDate() {//創建Ajax引擎對象var ajax;ajax = new XMLHttpRequest();//復寫onreadystatement函數ajax.onreadystatechange = function () {//判斷ajax狀態if(ajax.readyState == 4){//判斷響應狀態碼if(ajax.status == 200){//獲取響應內容var result = ajax.responseText;var showdiv = document.getElementById("showdiv");showdiv.innerHTML = result;}else if(ajax.status == 404){var showdiv = document.getElementById("showdiv");showdiv.innerText = "請求資源不存在"}else if(ajax.status == 500){var showdiv = document.getElementById("showdiv");showdiv.innerText = "服務器繁忙"}}else{var showdiv = document.getElementById("showdiv");showdiv.innerHTML=<img src='img/waiting.gif' width='200px' height='100px'/>;}}//發送請求ajax.open("get", "ajaxtest");ajax.send(null);} </script>在else選項中顯示waiting.gif圖片即可。
五 Ajax的請求方式
在使用Ajax技術的時候,我們要意識到ajax發送請求的時候,實際上請求還是瀏覽器發出的,只是瀏覽器知道這個請求是ajax發出的,當響應到來的時候,就不刷新整個界面了,而是響應給ajax;ajax再做其他的操作。所以對服務器來說,是沒有ajax方式還是普通方式請求的區別的。
GET
前面的例子,我們只是使用了簡單的get方式,當我們需要使用get來提交數據的時候,我們可以這樣寫
ajax.open("get", "ajaxtest?name=chester&pwd=123"); ajax.send(null);作為一個練習,你可以想象一下,如果我們要做一個用戶注冊功能,ajax部分的代碼應該如何寫。自然就是獲取用戶輸入,而后拼接到請求路徑中:
ajax.open("get", "ajaxtest?name=" + name + "&pwd=" + pwd);其中name 和 pwd這樣得到:
var name = document.getElementById("uname").value; var pwd = document.getElementById("pwd").value;POST
如果使用post方式提交數據,我們可以這樣寫
ajax.open("get", "ajaxtest"); ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); ajax.send(name=chester&pwd=123);注意這里加了一句:
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");這句話的意思是,告訴服務器按照鍵值對的方式解析post方式send的數據,否則服務器會認為只是普通的字符串提交。
六 Ajax的響應數據格式
以上就是Ajax技術的主要內容了,我們在來講講一個非常常見的問題,即數據交互問題,對于普通的簡單內容,可能直接一個普通字符串就可以了,就像上面的例子一樣,但是對于類似表格這樣的很多數內容應該如何處理呢?
有一點是毋庸置疑的,那就是我們在服務器端必須要保證,響應的格式要能被JS所解析,一種是普通字符串,另一種是JSON(重點)和XML;其實JSON也是一種字符串,但是用它來表示長長的數據(比如表格中的各項數據)比普通字符串要好得多,而且也很方便。
為了演示JSON的使用,我們編寫如下代碼:
mainPage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %><!doctype html> <html lang="ch"><head><title>mainPage</title><script type="text/javascript">function getTableDate() {//獲取用戶請求信息var name = document.getElementById("uname").value;var pwd = document.getElementById("pwd").value;//創建Ajax引擎對象var ajax;ajax = new XMLHttpRequest();//復寫onreadystatement函數ajax.onreadystatechange = function(){//判斷ajax狀態if(ajax.readyState == 4){//判斷響應狀態碼if(ajax.status == 200){//獲取響應內容var result = ajax.responseText;eval("var user=" + result);//獲取表格對象var ta = document.getElementById("ta");//插入新行var tr = ta.insertRow(1);//在新行插入數據var cell0 = tr.insertCell(0);cell0.innerHTML=user.uid;var cell1 = tr.insertCell(1);cell1.innerHTML=user.uname;var cell2 = tr.insertCell(2);cell2.innerHTML=user.pwd;}else if(ajax.status == 404){var showdiv = document.getElementById("showdiv");showdiv.innerText = "請求資源不存在"}else if(ajax.status == 500){var showdiv = document.getElementById("showdiv");showdiv.innerText = "服務器繁忙"}}}//發送請求ajax.open("get", "ajaxtest?name=" + name + "&pwd=" + pwd);ajax.send(null);}</script></head><body><hr>請輸入需要搜索的用戶名和密碼:<input type="text" name="uname" placeholder="Username" id="uname"/><input type="text" name="pwd" placeholder="Userpassword" id="pwd"/><input type="button" value="search" onclick="getTableDate()"><hr><table border="1px" id="ta"><tr><td>id</td><td>name</td><td>pwd</td></tr></table></body> </html>AjaxServlet.java
package com.chester.web.servlet;import com.chester.web.pojo.User; import com.chester.web.service.LoginService; import com.chester.web.service.impl.LoginServiceImpl; import com.google.gson.Gson;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException;@WebServlet("/ajaxtest") public class AjaxServlet extends HttpServlet{@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");String name = req.getParameter("name");String pwd = req.getParameter("pwd");System.out.println("用戶提交信息為" + name + pwd);LoginService ls = new LoginServiceImpl();User u = ls.checkLoginService(name, pwd);if(u != null){System.out.println("查詢到的用戶信息" + u);resp.getWriter().write(new Gson().toJson(u));}} }在代碼中,我們實現這樣一個功能,新建一個表格,提示用戶輸入用戶名和密碼,而后到后臺查詢信息,響應到表格中,效果如下所示:
輸入用戶名和密碼,點擊search后,顯示如下:
這里主要講解如下幾個代碼段,其他的都比較容易理解:
1 瀏覽器端JSON結果的獲取
//獲取響應內容var result = ajax.responseText;eval("var user=" + result);這里從服務器的響應獲取JSON格式的數據,而后將其賦給user變量,eval()函數是JS的一個函數,它可以計算某個字符串,并執行其中的的 JavaScript 代碼。為了知道result中的內容我們在其中插入一句:
//獲取響應內容var result = ajax.responseText;alert(result);eval("var user=" + result);再次查看響應,可以看到瀏覽器的提示框中輸出如下信息:
這是JSON的字符串。我們在表格中并沒用全部顯示這些信息,而是選擇了一部分顯示。
2 服務器端JSON數據的創建
關于服務器端JSON數據的創建比較簡單,我們使用了Google公司開發的jar包gson,直接在servlet中調用,當然你也可以自己拼接出這樣的字符串。
resp.getWriter().write(new Gson().toJson(u));使用Gson()類的toJson()方法將User中的數據域轉化成為JSON數據,非常的方便,其中User對象是這樣的:
public class User {private int uid;private String uname;private String pwd;private int sex;private int age;private String birth;public int getUid() {return uid;}public void setUid(int uid) {this.uid = uid;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public int getSex() {return sex;}public void setSex(int sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getBirth() {return birth;}public void setBirth(String birth) {this.birth = birth;}public String toString(){return getUname() + getPwd() + getBirth();} }如果輸入的是List對象,轉化的結果就是一個數組,數組的每一項就是List對象中的每一項數據對應的JSON數據,看起來類似于:
[{"uid":1,"uname":"Florence West","pwd":"123","sex":1,"age":18,"birth":"2000-10-10"}, {"uid":1,"uname":"Florence West","pwd":"123","sex":1,"age":18,"birth":"2000-10-10"}, {"uid":1,"uname":"Florence West","pwd":"123","sex":1,"age":18,"birth":"2000-10-10"}]這樣一來,我們就成功的將java中的數據對象傳遞給了JS對象。
關于使用XML傳遞數據,和JSON實際上大同小異:
數據發送端(java servlet):
//將響應數據類型告訴瀏覽器為XML格式 resp.setContentType("text/xml;charset=utf-8"); //發送數據給瀏覽器 resp.getWriter().write("<user><uid>1</uid><uname>chester</uname></user>");我們也可以使用jsp文件來實現這段代碼
數據接收端(js):
//獲取 var result = ajax.responseXML; //使用 alert(result.getElementsByTagName("uname")[0].innerHTML)可以看到XML比JSON要麻煩很多,而且,如果User對象改變,XML內容也需要更改,而JSON不用。所以如果我們需要數據傳輸,盡量使用JSON,XML一般是用來做配置文件。
經過上面的描述我們可以看到,如果在其他地方需要再次使用Ajax,有很多內容是重復的,這也引導我們也許可以將Ajax封裝成一個JS函數,這個任務并不難,可以自己嘗試一下。
總結
以上是生活随笔為你收集整理的Java Web - Ajax技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统-并发:死锁和饥饿
- 下一篇: Java Web - 服务器中的过滤器和