1. 程式人生 > >18、JavaScript增強AJAX基礎

18、JavaScript增強AJAX基礎

18、JavaScript增強AJAX基礎
要求
1)回顧JS中核心內容
2)瞭解WEB1.0和WEB2.0時代的技術與特點
3)理解AJAX的產生背景、工作原理與特點
4)掌握AJAX常用API及應用

宣告:今天服務端我們使用Servlet技術

一)什麼是JavaScript【以下簡稱JS】
JS是
(1)基於物件
JS本身就有一些現成的物件可供程式設計師使用,例如:Array,Math,String。。。
JS並不排除你可以自已按一定的規則建立物件
(2)事件驅動
JS程式碼寫好後,需要外界觸發後,方可執行,例如:單擊事件,定時執行,。。。
(3)解釋性
每次執行JS程式碼時,得需要將原始碼一行一行的解釋執行
相對編譯型語言(例如:Java、C++)執行速度相對較慢
(4)基於瀏覽器的動態互動網頁技術
如果JS嵌入到HTML中,可以不需要伺服器支援,直接由瀏覽器解釋執行
如果JS嵌入到JSP或Servlet中,必需要伺服器支援,直接由瀏覽器解釋執行
(5)嵌入在HTML標籤中
JS必須嵌入到一個名叫的標籤中,方可執行
指令碼語言

二)JS中的三種類型
(1)基本型別:number,string,boolean
number包含正數,負數,小數
string由”或”“定界
boolean由true或false,但js中的boolean也包含更多情況,例如:存在表示true,不存在表示false

    var num = 100;
        var str = "哈哈";
        var flag = false;
        window.alert(num);
        window.alert(str);
        window.alert(flag);

(2)特殊型別:null,undefined
null表示一個變數指向null
undefined表示一個變數指向的值不確定
var array = null;
var student;
alert(array);
alert(student);

(3)複合型別:函式,物件,陣列
物件包含內建物件和自定義的物件

三)JS中有三種定義函式的方式
(1)正常方式:function mysum(num1,num2){return num1+num2;}
function mysum(num1,num2){
return num1 + num2;
}
var myresult = mysum(100,200);
alert(“myresult=”+myresult);

(2)構造器方式:new Function(“num1”,”num2”,”return num1+num2;”)
var youresult = new Function(“num1”,”num2”,”return num1+num2”);
alert( youresult(1000,2000) );

(3)直接量或匿名或無名方式:var mysum = function(num1,num2){return num1+num2;}
var theyresult = function(num1,num2){
return num1 + num2;
}
alert( theyresult(10000,20000) );

四)JS中有四種物件
(1)內建物件 :Date,Math,String,Array,。。。

var str = new Date().toLocaleString();
        window.document.write("<font size='44' color='red'>"+str+"</font>");

(2)自定義物件:Person,Card,。。。

function Student(id,name,sal){
            //this指向s引用
            this.id = id;
            this.name = name;
            this.sal = sal;
        }
        var s = new Student(1,"波波",7000);
        document.write("編號:" + s.id + "<br/>");
        document.write("姓名:" + s.name + "<br/>");
        document.write("薪水:" + s.sal + "<br/>");

(3)瀏覽器物件: window,document,status,location,history。。。
function myrefresh(){
window.history.go(0);
}

(4)ActiveX物件:ActiveXObject(“Microsoft.XMLHTTP”),。。。

五)演示JS物件的屬性,方法和事件的使用
(1)window.location.href
var url = “04_array.html”;
window.location.href = url;

(2)form.submit()

<script type="text/javascript">
    function doSubmit(){
        //表單提交
        document.forms[0].submit();
    }
</script>

(3)inputElement.onblur = 函式
(4)document.createElement(“img”)
(5)imgElement.style.width/height

六)回顧傳統Web應用請求和響應特點【顯示當前時間】
(1)請求:瀏覽器以HTTP協議的方式提交請求到伺服器
(2)響應:伺服器以HTTP協議的方式響應內容到瀏覽器
注意:HTTP是WEB大眾化非安全協議
HTTPS是WEB安全協議,是基於HTTP協議的,且加了一些加密等特殊功能,常用於線上支付,或者是需要安全性較高的網站中,例如:12306網站
HTTP請求有三個部份組成:請求行,請求頭,請求體
HTTP響應有三個部份組成:響應行,響應頭,響應體
(3)狀態列:有明顯的進度條重新整理現象,如果伺服器響應較慢的話,進度條重新整理也會變慢,IE9等中高版本瀏覽器,有明顯轉圈圈圖示
(4)歷史欄:會收集原來已訪問過的web頁面,進行快取
(5)缺點:不需變化的大量資料,也全部重新整理,造成瀏覽器載入和處理負擔
(6)可改進的地方:讓不需變化的大量資料,原封不動,不用快取到歷史欄中,無需全部重新整理,只重新整理某些需要變化的資料區域,例如:當前時間的區域

當前時間:<span>${requestScope.str}</span><br/>
    <input type="button" value="同步方式提交"/>

    <script type="text/javascript">
        //定位button按鈕,同時新增單擊事件
        document.getElementsByTagName("input")[0].onclick = function(){
            var url = "${pageContext.request.contextPath}/TimeServlet?id="+new Date().getTime();
            window.location.href = url; 
        }
    </script>
public class TimeServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        System.out.println("TimeServlet::doGet");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = sdf.format(new Date());
        request.setAttribute("str",str);
        request.getRequestDispatcher("/06_time.jsp").forward(request,response);
    }
}

七)什麼是AJAX【Asynchronous非同步的JS和XML】,工作原理與特點
(1)什麼是同步:
請求1->響應1->請求2->響應2->
Web1.0時代

(2)什麼是非同步:
請求1->請求2->請求3->響應1->響應2->響應3->
請求1->響應1->請求2->請求3->響應2->響應3->
Web2.0時代
專案中:Web1.0為主(整個瀏覽器重新整理),Web2.0為輔(瀏覽器區域性重新整理)

(3)什麼是AJAX
客戶端(特指PC瀏覽器)與伺服器,可以在【不必重新整理整個瀏覽器】的情況下,與伺服器進行非同步通訊的技術
即,AJAX是一個【區域性重新整理】的【非同步】通訊技術
AJAX不是全新的語言,是2005年Google公司推出的一種全新【程式設計模式】,不是新的程式語言

(4)不用重新整理整個頁面便可與伺服器通訊的辦法有:
(A)Flash/ActionScript
(B)框架Frameset
(C)iFrame(內嵌入框架)
(D)XMLHttpRequest(非IE瀏覽器)和ActiveXObject(IE瀏覽器)
背景:早上IE5時,微軟就開發出了第一個非同步通訊物件,叫ActiveXObject物件,
Firefox等其它瀏覽器廠商也慢慢引入非同步通訊物件,叫XMLHttpRequest物件,
IE的高版本,也將這個非同步物件取名叫XMLHttpRequest物件,但IE有向下相容問題,
也可以使用ActiveXObject物件。
無需第三方jar包,現代中高版本瀏覽器中內建了這個非同步通訊物件,只需通過JavaScript就可以建立
注意:所有瀏覽器中都內建了非同步物件,在預設情況下,該非同步物件並沒有創建出來

function createAJAX(){
    var ajax = null;
    try{
        ajax = new ActiveXObject("microsoft.xmlhttp");
    }catch(e1){
        ajax = new XMLHttpRequest();
    }
    return ajax;
}

(5)AJAX工作原理
參見<

    當前時間:<span></span><br/>
    <input type="button" value="非同步方式提交"/>

<script type="text/javascript">
        //定位button按鈕,同時新增單擊事件
        document.getElementsByTagName("input")[0].onclick = function(){
            //NO1)建立AJAX非同步物件(每個瀏覽器內建的,無需第三方jar包)
            var ajax = createAJAX();//0
            //NO2)AJAX非同步物件準備傳送請求
            var url = "${pageContext.request.contextPath}/TimeServletAjax?id="+new Date().getTime();
            var method = "GET";
            ajax.open(method,url);//1
            //NO3)AJAX非同步物件真正傳送請求體的資料到伺服器,如果請求體無資料的話,用null表示
            var content = null;
            ajax.send(content);//2

            //----------------------------------------等待

            //NO4)AJAX非同步物件不斷監聽服務端狀態的變化,只有狀態碼變化了,方可觸發函式
            //0-1-2-3-4,這些是可以觸發函式的
            //4-4-4-4-4,這些是不可以觸發函式的
            //以下這個函式是伺服器來觸發的,不是程式設計師觸發的,這和onclick是不一樣的
            ajax.onreadystatechange = function(){
                //如果AJAX狀態碼為4
                if(ajax.readyState == 4){
                    //如果伺服器響應碼是200
                    if(ajax.status == 200){
                        //NO5)從AJAX非同步物件中獲取伺服器響應的結果
                        var str = ajax.responseText;
                        //NO6)按照DOM規則,將結果動態新增到web頁面指向的標籤中
                        document.getElementsByTagName("span")[0].innerHTML = str;
                    }
                }
            }
        } 
    </script>
public class TimeServletAjax extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = sdf.format(new Date());
        //注意:在Web2.0時代,即非同步方式下,不能用轉發或重定向
        //因為:轉發或重定向會引起瀏覽器全部重新整理,而不是區域性重新整理
        //所以得用以輸出流的方式將伺服器的結果輸出到瀏覽器
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.write(str);
        pw.flush();
        pw.close();
    }
}

(2)基於HTML,以GET或POST方式,檢查註冊使用者名稱是否在資料庫中已存在(text/html;charset=UTF-8)
輸入使用者名稱[POST]:游標移出後,立刻顯示結果



public class RegisterServletPost extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String username = request.getParameter("username");
        String tip = "images/MsgSent.gif";
        if("傑克".equals(username)){
            tip = "images/MsgError.gif";
        }
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.write(tip);
        pw.flush();
        pw.close();
    }
}

(3)基於XML,以POST方式,完成省份-城市二級下拉聯動
(text/xml;charset=UTF-8)

    <select id="province" style="width:111px">
        <option>選擇省份</option>
        <option>廣東</option>
        <option>湖南</option>
        <option>湖北</option>
    </select>

    <select id="city" style="width:111px">
        <option>選擇城市</option>
    </select>

<script type="text/javascript">
        //定位省份下拉框,同時添時內容改變事件
        document.getElementById("province").onchange = function(){
            //清除城市下拉框中的內容除第一項外
            var citySelectElement = document.getElementById("city");
            citySelectElement.options.length = 1;
            //獲取選中的省份
            var i = this.selectedIndex;
            var optionElement = this[i];
            var province = optionElement.innerHTML;
            //如果不是"選擇省份"的話
            if("選擇省份" != province){
                //NO1)
                var ajax = createAJAX();
                //NO2)
                var method = "POST";
                var url = "${pageContext.request.contextPath}/ProvinceCityServlet?id="+new Date().getTime();
                ajax.open(method,url);
                ajax.setRequestHeader("content-type","application/x-www-form-urlencoded");
                //NO3)
                var content = "province="+province;
                ajax.send(content);

                //-------------------------------------------------

                //NO4)
                ajax.onreadystatechange = function(){
                    if(ajax.readyState == 4){
                        if(ajax.status == 200){
                            //NO5)
                            var xmlDocument = ajax.responseXML;
                            //NO6)按照dom規則,解析xml檔案中的所有內容
                            var cityElementArray = xmlDocument.getElementsByTagName("city");
                            var size = cityElementArray.length;                         
                            for(var i=0;i<size;i++){
                                var cityElement = cityElementArray[i];
                                //innerHTML只能用於html和jsp頁面,不能用於xml頁面
                                //在xml頁面我們通常用firstChild.nodeValue去替代innerHTML
                                var city = cityElement.firstChild.nodeValue;
                                //<option></option>
                                var optionElement = document.createElement("option");
                                //<option>廣州</option>
                                optionElement.innerHTML = city;
                                //<select id="city" style="width:111px"><option>廣州</option></select>
                                citySelectElement.appendChild(optionElement);
                            }
                        }
                    }
                }
            }
        }
    </script>
public class ProvinceCityServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        this.doPost(request,response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String province = request.getParameter("province");

        response.setContentType("text/xml;charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.write("<?xml version='1.0' encoding='UTF-8'?>");
        pw.write("<root>");

        if("廣東".equals(province)){
            pw.write("<city>廣州</city>");
            pw.write("<city>深圳</city>");
            pw.write("<city>中山</city>");
            pw.write("<city>珠海</city>");
        }else if("湖南".equals(province)){
            pw.write("<city>長沙</city>");
            pw.write("<city>株洲</city>");
            pw.write("<city>張家界</city>");
        }else if("湖北".equals(province)){
            pw.write("<city>武漢</city>");
            pw.write("<city>黃崗</city>");
        }

        pw.write("</root>");
        pw.flush();
        pw.close();
    }
}

(4)驗證碼檢查
(text/html;charset=UTF-8)

    <form>
        驗證碼:
        <input type="text" maxlength="4" size="4"/>
        <img src="image.jsp"/>
        <input type="button" value="看不清" size="2"/>
        <span></span>
    </form>

`

這裡寫程式碼片`<script type="text/javascript">
        //定位按鈕,同時新增單擊事件
        document.getElementsByTagName("input")[1].onclick = function(){
            //定位img標籤,修改src屬性
            document.images[0].src = "image.jsp?id="+new Date().getTime();
            //清空span標籤中的內容
            var spanElement = document.getElementsByTagName("span")[0];
            spanElement.innerHTML = "";
            //清空文字框中的內容
            document.getElementsByTagName("input")[0].value = "";
        }
    </script>

    <script type="text/javascript">
        //定位文字框,同時新增鍵盤彈起事件
        document.getElementsByTagName("input")[0].onkeyup = function(){
            //獲取輸入的驗證碼
            var checkcode = this.value;
            //去空格
            checkcode = trim(checkcode);
            //獲取驗證碼的長度
            var size = checkcode.length;
            //如果長度為4
            if(size == 4){
                //NO1)
                var ajax = createAJAX();
                //NO2)
                var method = "POST";
                var url = "${pageContext.request.contextPath}/CheckcodeServlet?id="+new Date().getTime();
                ajax.open(method,url);
                ajax.setRequestHeader("content-type","application/x-www-form-urlencoded");
                //NO3)
                var content = "checkcode=" + checkcode; 
                ajax.send(content);

                //--------------------------------------------

                //NO4)
                ajax.onreadystatechange = function(){
                    if(ajax.readyState == 4){
                        if(ajax.status == 200){
                            //NO5)
                            var imagePath = ajax.responseText;

                            //NO6)
                            var imgElement = document.createElement("img");
                            imgElement.src = imagePath;
                            imgElement.style.width = "14px";
                            imgElement.style.height = "14px";
                            var spanElement = document.getElementsByTagName("span")[0];
                            spanElement.innerHTML = "";
                            spanElement.appendChild(imgElement);
                        }
                    }
                }
            }else{
                //清空span標籤中的內容
                var spanElement = document.getElementsByTagName("span")[0];
                spanElement.innerHTML = "";
            }
        }
    </script>
public class CheckcodeServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        //獲取客戶端輸入的驗證碼
        String checkcodeClient = request.getParameter("checkcode");
        //獲取服務端產生的驗證碼 
        HttpSession httpSession = request.getSession();
        String checkcodeServer = (String) httpSession.getAttribute("CHECKNUM");
        //二個驗證碼進行比較
        String tip = "images/MsgError.gif";
        if(checkcodeClient!=null && checkcodeServer!=null && checkcodeClient.equals(checkcodeServer)){
            tip = "images/MsgSent.gif";
        }
        //以流的方式輸出tip變數
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.write(tip);
        pw.flush();
        pw.close();
    }
}

九)XMLHttpRequest(即:AJAX)物件常用事件,方法和屬性
(1)事件:
ajax.onreadystatechange:表示AJAX非同步物件不斷監聽服務端的響應,
是由伺服器程式觸發,不是程式設計師觸發

(2)屬性:
ajax.readyState==0:表示AJAX非同步物件已建立好,但還沒有呼叫open()方法

    ajax.readyState==1:表示AJAX非同步物件已呼叫open()方法,但還沒有呼叫send()方法

    ajax.readyState==2:表示AJAX非同步物件已呼叫send()方法,但請求還沒有到達伺服器端

    ajax.readyState==3:表示服務端已接收到AJAX非同步物件的請求,正在處理響應中。。。

ajax.readyState==【4】:表示AJAX非同步物件已經完完全全接收到了伺服器的響應信 息,但接收到的資料不一定都正確
上述5種狀態不是所有瀏覽器都相同,但狀態4每種瀏覽器都相同

    ajax.status==200:表示AJAX非同步物件接收到響應碼,如果是200的話,表示一切正常

    ajax.responseText:表示從AJAX非同步物件中獲取HTML載體中的資料

    ajax.responseXML:表示從AJAX非同步物件中獲取XML載體中的資料

(3)方法:
ajax.open(method,url,可選的boolean值)
AJAX非同步物件準備傳送非同步請求
引數一:以什麼方式傳送,常用的用GET或POST,大小寫不敏感
引數二:傳送到什麼地方去,常用Servlet或Struts2或SpringMVC來接收,
這裡只限於JavaEE學科
引數三:預設值為true,表示AJAX物件以【非同步】的方式提交到服務端
如果設定為false,表示AJAX物件以【同步】的方式提交到服務端

    ajax.setRequestHeader("content-type","application/x-www-form-urlencoded")
    表示將請求體中的內容,按照UTF-8的方式進行編碼,只針對POST請求有效   

    ajax.send(content)
    AJAX非同步物件真正傳送非同步請求
    引數一:表示HTTP【請求體】中的內容
    如果是GET方式:content = null,如果強行傳值到伺服器,服務端收不到,返回NULL
    如果是POST方式:content != null,例如:username=jack&password=123&role=admin

十)資料載體
(1)HTML
(A)優點:服務端響應的是普通html字串,無需JS解析,配合innerHTML屬性效率高
(B) 缺點:如果需要更新WEB頁面中的很多處地方,HTML不太方便,同時innerHTML屬性不是DOM的標準,不能操作XML
注意:innerHTML在xml中不能使用,用firstChild.nodeValue替代
(C)適合:小量資料載體,且只更新在web頁面中的一個地方

(2)XML
(A)優點:是種通用的普通字串格式,任何技術都能解析,標籤名可以任意,使用DOM標準規則能夠解析XML的任何部分
(B)缺點:XML檔案格式相當嚴格,出錯後,responseXML屬性返回NULL,如果XML檔案過長,導致解析效率低下
(C)適合:大量具有層次資料載體

(3)JSON (下次課講)+ struts2框架
兼備HTML和XML的特點

作業:服務端採用Servlet完成

1)檢查註冊使用者名稱是否在資料庫中存在
2)省份-城市二級聯動
3)驗證碼識別