摘要:性能會有所降低一點內(nèi)容,刷新整個頁面用戶的操作頁面會中斷整個頁面被刷新了就是能夠做到局部刷新三對象是中最重要的一個對象。頭信息已經(jīng)接收,響應(yīng)數(shù)據(jù)尚未接收。
一、什么是Ajax
Ajax(Asynchronous JavaScript and XML) 異步JavaScript和XML
Ajax實際上是下面這幾種技術(shù)的融合:
(1)XHTML和CSS的基于標(biāo)準(zhǔn)的表示技術(shù)
(2)DOM進(jìn)行動態(tài)顯示和交互
(3)XML和XSLT進(jìn)行數(shù)據(jù)交換和處理
(4)XMLHttpRequest進(jìn)行異步數(shù)據(jù)檢索
(5)Javascript將以上技術(shù)融合在一起
客戶端與服務(wù)器,可以在【不必刷新整個瀏覽器】的情況下,與服務(wù)器進(jìn)行異步通訊的技術(shù)
二、為什么我們需要Ajax?在我們之前的開發(fā),每當(dāng)用戶向服務(wù)器發(fā)送請求,哪怕只是需要更新一點點的局部內(nèi)容,服務(wù)器都會將整個頁面進(jìn)行刷新。
性能會有所降低(一點內(nèi)容,刷新整個頁面!)
用戶的操作頁面會中斷(整個頁面被刷新了)
Ajax就是能夠做到局部刷新!
三、XMLHttpRequestXMLHttpRequest對象是Ajax中最重要的一個對象。使用Ajax更多的是編寫客戶端代碼,而不是服務(wù)端的代碼。
3.1XMLHttpRequest 工作原理傳統(tǒng)的web前端與后端的交互中,瀏覽器直接訪問Tomcat的Servlet來獲取數(shù)據(jù)。Servlet通過轉(zhuǎn)發(fā)把數(shù)據(jù)發(fā)送給瀏覽器。
當(dāng)我們使用AJAX之后,瀏覽器是先把請求發(fā)送到XMLHttpRequest異步對象之中,異步對象對請求進(jìn)行封裝,然后再與發(fā)送給服務(wù)器。服務(wù)器并不是以轉(zhuǎn)發(fā)的方式響應(yīng),而是以流的方式把數(shù)據(jù)返回給瀏覽器
XMLHttpRequest異步對象會不停監(jiān)聽服務(wù)器狀態(tài)的變化,得到服務(wù)器返回的數(shù)據(jù),就寫到瀏覽器上【因為不是轉(zhuǎn)發(fā)的方式,所以是無刷新就能夠獲取服務(wù)器端的數(shù)據(jù)】
3.2創(chuàng)建XMLHttpRequest對象要創(chuàng)建XMLHttpRequest對象是要分兩種情況考慮的:
在IE6以下的版本
在IE6以上的版本以及其他內(nèi)核的瀏覽器(Mozilla)等
3.3了解XMLHttpRequest對象的屬性和方法 3.3.1方法
open()(String method,String url,boolean asynch,String username,String password)
send(content)
setRequestHeader(String header,String value)
getAllResponseHeaders()
getResponseHeader(String header)
abort()
常用的方法就是黑色粗體的前三個
open():該方法創(chuàng)建http請求
第一個參數(shù)是指定提交方式(post、get)
第二個參數(shù)是指定要提交的地址是哪
第三個參數(shù)是指定是異步還是同步(true表示異步,false表示同步)
第四和第五參數(shù)在http認(rèn)證的時候會用到。是可選的
setRequestHeader(String header,String value):設(shè)置消息頭(使用post方式才會使用到,get方法并不需要調(diào)用該方法)
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
send(content):發(fā)送請求給服務(wù)器
如果是get方式,并不需要填寫參數(shù),或填寫null
如果是post方式,把要提交的參數(shù)寫上去
3.3.2屬性onreadystatechange:請求狀態(tài)改變的事件觸發(fā)器(readyState變化時會調(diào)用此方法),一般用于指定回調(diào)函數(shù)
readyState:請求狀態(tài)readyState一改變,回調(diào)函數(shù)被調(diào)用,它有5個狀態(tài)
0:未初始化
1:open方法成功調(diào)用以后
2:服務(wù)器已經(jīng)應(yīng)答客戶端的請求
3:交互中。Http頭信息已經(jīng)接收,響應(yīng)數(shù)據(jù)尚未接收。
4:完成。數(shù)據(jù)接收完成
responseText:服務(wù)器返回的文本內(nèi)容
responseXML:服務(wù)器返回的兼容DOM的XML內(nèi)容
status:服務(wù)器返回的狀態(tài)碼
statusText:服務(wù)器返回狀態(tài)碼的文本信息
上面有兩個地方都提及了回調(diào)函數(shù),回調(diào)函數(shù)是什么??
回調(diào)函數(shù)就是接收服務(wù)器返回的內(nèi)容!
四、編寫第一個Ajax程序檢測用戶輸入的用戶名是否為"zhongfucheng",只要不是zhongfucheng,就可以使用!
4.1html代碼創(chuàng)建的div只要用于顯示服務(wù)器返回的數(shù)據(jù)
當(dāng)用戶點擊按鈕的時候,就觸發(fā)事件。
4.2JavaScript代碼
創(chuàng)建XMLHttpRequest對象
創(chuàng)建http請求
把文本框的數(shù)據(jù)發(fā)送給http請求的目標(biāo)
指定回調(diào)函數(shù)
編寫回調(diào)函數(shù)
發(fā)送http請求
回調(diào)函數(shù)得到http返回的內(nèi)容,把內(nèi)容寫在div上
4.3效果
實現(xiàn)了局部更新,不需要刷新整一個頁面
五、XMLHttpRequest解決中文亂碼在傳統(tǒng)的Web中我們已經(jīng)解決過中文亂碼問題了。
服務(wù)器傳送給瀏覽器數(shù)據(jù)發(fā)生亂碼:response設(shè)置編碼的時候和瀏覽器頁面的編碼一致便可以解決
瀏覽器傳送給服務(wù)器數(shù)據(jù)發(fā)生亂碼:如果是post方式,request設(shè)置編碼便可以解決。如果是get方式,Tomcat下,使用ISO8859-1編碼得到原本的二進(jìn)制數(shù)組,再使用UTF-8編碼便可以解決
接下來,要介紹的是:我們可以屏蔽任何瀏覽器和任何服務(wù)器的編碼格式,瀏覽器發(fā)送給服務(wù)器的數(shù)據(jù)不造成亂碼問題!
具體我們是這樣做的:
發(fā)送數(shù)據(jù)給服務(wù)器的時候,JavaScript使用兩次EncodeURI()
服務(wù)器得到數(shù)據(jù),使用URLEncode.decode(數(shù)據(jù),"utf-8")進(jìn)行解碼
為啥我能說這種方式屏蔽任何瀏覽器和服務(wù)器的編碼格式,都不會亂碼呢??
六、XMLHttpRequest解決緩存問題在傳統(tǒng)的Web中我們也解決過緩存的問題,通過設(shè)置response的頭信息,返回給瀏覽器就可以實現(xiàn)不緩存頁面了。
但是呢,現(xiàn)在我們使用XMLHttpRequest,拿到的不是全新的頁面,僅僅是服務(wù)器端發(fā)送過來的數(shù)據(jù)!!
那我們要怎么解決緩存的問題呢??產(chǎn)生緩存的原因就是:我們請求了同一個地址,做了相同的操作。服務(wù)端認(rèn)為我的操作并沒有什么變化,就直接把緩存的信息給我了。這樣的話,我就不能更換驗證碼圖片了(等等應(yīng)用)。
我們可以這樣做:
在每次請求url中加入一個時間戳參數(shù)【每次url就不一樣了】
加入時間戳參數(shù)到url時,也分兩種情況
url本身就帶有參數(shù)了,也就是說有"?"號了,那么添加時間戳的時候就需要用"&"號
[x] url沒有參數(shù),直接使用"?"號來添加時間戳
if(url.indexOf("?") >= 0){ url = url + "&t=" + (new Date()).valueOf(); } else{ url = url + "?t=" + (new Date()).valueOf(); }七、XMLHttpRequest跨域訪問
使用XMLHttpRequest去跨域訪問是會出現(xiàn)錯誤的。
我們要怎么解決呢??這時候就要用代理思想了
XMLHttpRequest先把請求提交給同域的Servlet處理
同域Servlet再將XMLHttpRequest的請求提交給跨域的服務(wù)器
同域Servlet得到跨域服務(wù)器的返回值,再返回給XMLHttpRequest
這個時候,XMLHttpRequest跨域訪問就分兩種(GET和POST)情況了,因為這兩種提交數(shù)據(jù)的方式是不一樣的!
7.1瀏覽器代碼我們需要在調(diào)用open方法之前判斷一下要連接的地址是不是以http開頭的,如果是則認(rèn)為要訪問的是跨域的資源
首先將當(dāng)前url中的”?”變成”&”,這是因為將要連接的地址改為”Proxy?url=” + url以后,如果原來url地址中有參數(shù)的話,新的url地址中就會有兩個“?”這會導(dǎo)致服務(wù)器端解析參數(shù)錯誤,”url=”之后的內(nèi)容表示本來要訪問的跨域資源的地址。
7.2GET方式GET方式是直接把參數(shù)的信息都放在url地址上,所以處理起來會相對簡單。
步驟:
使用StringBuilder裝載著getParameter("url")【獲取得到地址,呆會要做拼接,所以用StringBuilder】
得到其他參數(shù)的時候,做URLEncode.encode(),因為我們進(jìn)入Servlet的時候已經(jīng)被decode了一次【我們要盡可能保留原始請求】(參照解決中文亂碼)
遍歷所有的請求參數(shù),只要名字不是"url",就添加到StringBuilder中【第一個參數(shù)為"?",其他的參數(shù)為"&"】(http://localhost:8080/url?aa=bb&cc=dd)
創(chuàng)建URL對象,把拼接成的StringBuilder傳遞進(jìn)去
使用BufferReader讀取遠(yuǎn)程服務(wù)器返回的數(shù)據(jù),要指定輸入流編碼格式,否則會亂碼
BufferedReader reader = new BufferedReader(new InputStreamReader(URL對象.openSteam(),"UTF-8"));
最后,把遠(yuǎn)程服務(wù)器讀取到的數(shù)據(jù)再返回給XMLHttpRequest
7.3POST方式POST方式把參數(shù)的信息都封裝到HTTP請求中,在URL進(jìn)行連接的時候,需要把數(shù)據(jù)寫給遠(yuǎn)程服務(wù)器
步驟:
得到url參數(shù),創(chuàng)建StringBuilder
得到其他參數(shù)的時候,做URLEncode.encode(),因為我們進(jìn)入Servlet的時候已經(jīng)被decode了一次【我們要盡可能保留原始請求】(參照解決中文亂碼)
遍歷所有的請求參數(shù),只要名字不是"url",就添加到StringBuilder中【第一個參數(shù)直接給出,其他的參數(shù)為"&"】(aa=bb&cc=dd&ee=ff)
創(chuàng)建URL對象,創(chuàng)建URL連接器,允許寫數(shù)據(jù)到遠(yuǎn)程服務(wù)器上
URL url = new URL(url); URLConnection connection = url.openConnection; connection.setDoOutPut(true);
得到寫數(shù)據(jù)流
OutputSteamWriter writer = new OutputSteamWriter(conncetion.getOutputSteam)
把StringBuilder的數(shù)據(jù)寫到遠(yuǎn)程服務(wù)器上,并flush
使用BufferReader讀取遠(yuǎn)程服務(wù)器返回的數(shù)據(jù)
BufferedReader reader = new BufferedReader(new InputSteamReader(conncetion.inputSteamReader,"UTF-8"));八、AJAX二級下拉聯(lián)動案例【XML版】
我們在購物的時候,常常需要我們來選擇自己的收貨地址,先選擇省份,再選擇城市...
有沒有發(fā)現(xiàn):當(dāng)我們選擇完省份的時候,出現(xiàn)的城市全部都是根據(jù)省份來給我們選擇的。這是怎么做到的呢???其實就是通過AJAX來完成的。使用AJAX技術(shù)讓我們看起來網(wǎng)頁非?!爸悄堋?,會根據(jù)省份來給出對應(yīng)的城市信息。
我們這里就不讀取數(shù)據(jù)庫了,直接在Servlet寫死數(shù)據(jù)來進(jìn)行模擬測試。
8.1分析我們知道AJAX與服務(wù)器之間的交互常用的傳輸載體格式有三種:
HTML
XML
JSON
由于省份與城市是有層級關(guān)系的,因此我們只能用XML或者JSON。
我們這里首先就用XML來進(jìn)行,后面會使用JSON,來看看他倆有什么不同的地方。。
8.1.1前臺分析當(dāng)用戶選擇了某個省份之后,就使用AJAX與服務(wù)器進(jìn)行交互,那么在選擇城市的時候就出現(xiàn)對應(yīng)的城市信息。
監(jiān)聽下拉框值變化事件
只要下拉框值變化了,就與服務(wù)器進(jìn)行交互
得到服務(wù)器返回的值,解析XML
使用DOM把數(shù)據(jù)寫到城市下拉框列表中
8.1.2后臺分析得到前臺帶過來的數(shù)據(jù)
判斷該數(shù)據(jù)是什么,返回對應(yīng)的的XML文件
8.2寫JSP頁面<%-- Created by IntelliJ IDEA. User: ozc Date: 2017/5/17 Time: 19:38 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %>8.3Servlet多級聯(lián)動 <%--############前臺頁面###################--%> <%--############AJAX###################--%>
import java.io.IOException; import java.io.PrintWriter; /** * Created by ozc on 2017/5/17. */ @javax.servlet.annotation.WebServlet(name = "ProvinceServlet",urlPatterns = "/ProvinceServlet") public class ProvinceServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //設(shè)置中文編碼 request.setCharacterEncoding("UTF-8"); String province = request.getParameter("province"); //這里是返回的是XML,因此指定XML數(shù)據(jù)! response.setContentType("text/xml;charset=UTF-8"); PrintWriter printWriter = response.getWriter(); /****************返回XML文件給前臺**************/ printWriter.write(""); printWriter.write("8.4效果: 8.5XML方式總結(jié)"); if("廣東".equals(province)){ printWriter.write(" "); System.out.println("1111"); /*******事后操作*******/ printWriter.flush(); printWriter.close(); } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { this.doPost(request, response); } }廣州 "); printWriter.write("深圳 "); printWriter.write("中山 "); }else if("湖南".equals(province)){ printWriter.write("長沙 "); printWriter.write("株洲 "); printWriter.write("湘潭 "); printWriter.write("岳陽 "); } printWriter.write("
監(jiān)聽下拉框的變化,如果變化了,那么就使用異步操作去訪問服務(wù)器,得到對應(yīng)的數(shù)據(jù)返回給異步對象
異步對象解析服務(wù)器帶過來的數(shù)據(jù),使用DOM編程把數(shù)據(jù)動態(tài)添加到頁面上
在Servlet上記得要指定返回的是XML的數(shù)據(jù)!
在前臺解析XML文檔的時候,不能直接使用innerHtml來得到節(jié)點的值,只能通過firstChild.nodeValue的方式獲取。
由于每次append到下拉框都會連續(xù)append,因此在響應(yīng)事件的時候,把下拉框清零
把下拉框options的長度賦值為1,那么就是清零的操作了。
九、AJAX二級下拉聯(lián)動案例【JSON版】前面我們已經(jīng)使用過了XML作為數(shù)據(jù)載體在AJAX中與服務(wù)器進(jìn)行交互。當(dāng)時候我們的案例是二級聯(lián)動,使用Servlet進(jìn)行控制
這次我們使用JSON作為數(shù)據(jù)載體在AJAX與服務(wù)器交互,使用三級聯(lián)動,使用Action進(jìn)行控制....
省份-城市-區(qū)域三級聯(lián)動【Struts2 + JSON版】
9.1分析與上次是一樣的,只不過這次換了用JSON,使用Action控制罷了...
監(jiān)聽下拉框的變動,使用異步對象與服務(wù)器進(jìn)行交互。
9.1.1前臺分析監(jiān)聽下拉框的變動
得到服務(wù)器返回的JSON數(shù)據(jù)
使用eval()進(jìn)行解析,得到具體的對象
使用DOM編程把數(shù)據(jù)填充到對應(yīng)的下拉框上
9.1.2后臺分析得到前臺發(fā)送過來的數(shù)據(jù)
判斷具體的數(shù)據(jù)是什么,給出對應(yīng)的數(shù)據(jù)
使用Struts2提供的組件把數(shù)據(jù)封裝成JSON
返回給瀏覽器
9.2監(jiān)聽省份JSP頁面<%-- Created by IntelliJ IDEA. User: ozc Date: 2017/5/18 Time: 13:36 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %>9.3監(jiān)聽省份Action使用JSON數(shù)據(jù)載體與服務(wù)器進(jìn)行交互 <%--############前臺頁面##############################--%> <%--############監(jiān)聽省份##############################--%>
要想Struts2能夠把Action的數(shù)據(jù)封裝成JSON,就需要導(dǎo)入Struts2的開發(fā)包
struts2-json-plugin-2.3.4.1.jar
在Action中對應(yīng)的成員屬性需要給getter方法
import com.opensymphony.xwork2.ActionSupport; import java.util.ArrayList; import java.util.List; /** * Created by ozc on 2017/5/18. */ public class ProvinceAction extends ActionSupport{ //自動封裝數(shù)據(jù) private Bean bean; public Bean getBean() { return bean; } public void setBean(Bean bean) { this.bean = bean; } //封裝城市的集合 private Listcity = new ArrayList<>(); public List getCity() { return city; } public String findCityByProvince() throws Exception { if ("廣東".equals(bean.getName())) { city.add("廣州"); city.add("珠海"); city.add("從化"); } else if ("北京".equals(bean.getName())) { city.add("一環(huán)"); city.add("二環(huán)"); city.add("三環(huán)"); city.add("四環(huán)"); } else { System.out.println("沒有你選擇的地區(qū)"); } return "ok"; } }
返回給前端的時候,數(shù)據(jù)是這樣子的:
9.4效果 9.5監(jiān)聽城市JSP<%--############監(jiān)聽城市##############################--%>9.6Action頁面
public String findAreaByCity() throws Exception { if ("廣州".equals(bean.getName())) { area.add("白云區(qū)"); area.add("黃浦區(qū)"); area.add("蘿崗區(qū)"); } else if ("珠海".equals(bean.getName())) { area.add("香江"); area.add("拱北"); area.add("EE"); area.add("xx"); } else { System.out.println("沒有你選擇的地區(qū)"); } return "ok"; }9.7最終效果: 9.8總結(jié)
這次使用的是JSON作為數(shù)據(jù)載體與服務(wù)器進(jìn)行交互,和XML本質(zhì)上是沒有區(qū)別的。
只不過JSON是更加輕量級文本數(shù)據(jù),在JavaScript能夠方便地獲取返回的數(shù)據(jù)
在Struts2中把Action數(shù)據(jù)封裝成JSON格式,返回給異步對象
需要導(dǎo)入jar包
在配置文件中配置繼承json包
返回的類型是json
如果使用POST時,發(fā)送的key、vaulue太多的話,我們可以使用bean進(jìn)行封裝
當(dāng)選中省份時,把城市和區(qū)域的下拉框清空,當(dāng)選擇城市時,把區(qū)域的下拉框清空
十、總結(jié)圖如果文章有錯的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號:Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76323.html
摘要:前言由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號:Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...
摘要:前言上一次我們對的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來聊聊。 showImg(https://segmentfault.com/img/remote/1460000020077803?w=1280&h=853); 前言 上一次我們對Paging的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來聊聊WorkManager。 如果你對Paging還未了解,推薦閱讀這篇文章: Paging在Recy...
摘要:采用完全獨立于任何程序語言的文本格式,使成為理想的數(shù)據(jù)交換語言為什么需要提到,我們就應(yīng)該和來進(jìn)行對比。也是一種存儲和交換文本信息的手段。那么好在哪里呢比更小更快,更易解析。使用的時候,也支持將轉(zhuǎn)成但是,我們不一定使用框架來做開發(fā)呀。 什么是JSON JSON:JavaScript Object Notation 【JavaScript 對象表示法】 JSON 是存儲和交換文本信息的語法...
摘要:目錄前言架構(gòu)安裝第一個爬蟲爬取有道翻譯創(chuàng)建項目創(chuàng)建創(chuàng)建解析運行爬蟲爬取單詞釋義下載單詞語音文件前言學(xué)習(xí)有一段時間了,當(dāng)時想要獲取一下百度漢字的解析,又不想一個個漢字去搜,復(fù)制粘貼太費勁,考慮到爬蟲的便利性,這篇文章是介紹一個爬蟲框架, 目錄 前言 架構(gòu) 安裝 第一個爬蟲:爬取有道翻譯 創(chuàng)建項目 創(chuàng)建Item 創(chuàng)建Spider 解析 運行爬蟲-爬取單詞釋義 下載單詞語音文件 ...
摘要:要是使用到日歷的話,我們想到使用這個日歷類上面僅僅是我個人總結(jié)的要點,如果有錯誤的地方還請大家給我指正。 納稅服務(wù)系統(tǒng)總結(jié) 納稅服務(wù)系統(tǒng)是我第一個做得比較大的項目(不同于javaWeb小項目),該項目系統(tǒng)來源于傳智Java32期,十天的視頻課程(想要視頻的同學(xué)關(guān)注我的公眾號就可以直接獲取了) 我跟著練習(xí)一步一步完成需求,才發(fā)覺原來Java是這樣用來做網(wǎng)站的,Java有那么多的類庫,頁面...
閱讀 1957·2021-11-22 15:33
閱讀 3001·2021-11-18 10:02
閱讀 2602·2021-11-08 13:16
閱讀 1617·2021-10-09 09:57
閱讀 1366·2021-09-30 09:47
閱讀 2000·2019-08-29 13:05
閱讀 3064·2019-08-29 12:46
閱讀 1004·2019-08-29 12:19