天天看點

AjaxAJAX(Asynchronous Javascript And Xml)

AJAX(Asynchronous Javascript And Xml)

傳統請求及缺點

  • 傳統的請求都有哪些?
    • 直接在浏覽器位址欄上輸入URL。
    • 點選超連結
    • 送出form表單
    • 使用JS代碼發送請求
      • window.open(url)
      • document.location.href = url
      • window.location.href = url
      • ....
  • 傳統請求存在的問題
    • 頁面全部重新整理導緻了使用者的體驗較差。
    • 傳統的請求導緻使用者的體驗有空白期。(使用者的體驗是不連貫的)

AJAX概述

  • AJAX不能稱為一種技術,它是多種技術的綜合産物。
  • AJAX可以讓浏覽器發送一種特殊的請求,這種請求可以是:異步的。
  • 什麼是異步,什麼是同步?
    • 假設有t1和t2線程,t1和t2線程并發,就是異步。
    • 假設有t1和t2線程,t2在執行的時候,必須等待t1線程執行到某個位置之後t2才能執行,那麼t2在等t1,顯然他們是排隊的,排隊的就是同步。
    • AJAX是可以發送異步請求的。也就是說,在同一個浏覽器頁面當中,可以發送多個ajax請求,這些ajax請求之間不需要等待,是并發的。
  • AJAX代碼屬于WEB前端的JS代碼。和後端的java沒有關系,後端也可以是php語言,也可以是C語言。
  • AJAX 應用程式可能使用 XML 來傳輸資料,但将資料作為純文字或 JSON 文本傳輸也同樣常見。
  • AJAX可以更新網頁的部分,而不需要重新加載整個頁面。(頁面局部重新整理)
  • AJAX可以做到在同一個網頁中同時啟動多個請求,類似于在同一個網頁中啟動“多線程”,一個“線程”一個“請求”。
  • AjaxAJAX(Asynchronous Javascript And Xml)
  • AjaxAJAX(Asynchronous Javascript And Xml)

XMLHttpRequest對象

  • XMLHttpRequest對象是AJAX的核心對象,發送請求以及接收伺服器資料的傳回,全靠它了。
  • XMLHttpRequest對象,現代浏覽器都是支援的,都内置了該對象。直接用即可。
  • 建立XMLHttpRequest對象
    • var xhr = new XMLHttpRequest();
                 
  • XMLHttpRequest對象的方法
方法 描述
abort() 取消目前請求
getAllResponseHeaders() 傳回頭部資訊
getResponseHeader() 傳回特定的頭部資訊
open(method, url, async, user, psw) 規定請求method:請求類型 GET 或 POSTurl:檔案位置async:true(異步)或 false(同步)user:可選的使用者名稱psw:可選的密碼
send() 将請求發送到伺服器,用于 GET 請求
send(string) 将請求發送到伺服器,用于 POST 請求
setRequestHeader() 向要發送的報頭添加标簽/值對
  • XMLHttpRequest對象的屬性
屬性 描述
onreadystatechange 定義當 readyState 屬性發生變化時被調用的函數
readyState 儲存 XMLHttpRequest 的狀态。0:請求未初始化 1:伺服器連接配接已建立 2:請求已收到 3:正在處理請求 4:請求已完成且響應已就緒
responseText 以字元串傳回響應資料
responseXML 以 XML 資料傳回響應資料
status 傳回請求的狀态号200: "OK"403: "Forbidden"404: "Not Found"
statusText 傳回狀态文本(比如 "OK" 或 "Not Found")

AJAX GET請求

  • 發送AJAX get請求,前端代碼:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>發送ajax get請求</title>
    </head>
    <body>
    <script type="text/javascript">
        window.onload = function () {
            document.getElementById("btn").onclick = function () {
                //1. 建立AJAX核心對象
                var xhr = new XMLHttpRequest();
                //2. 注冊回調函數
                xhr.onreadystatechange = function(){
                    if (this.readyState == 4) {
                        if (this.status == 200) {
                            // 通過XMLHttpRequest對象的responseText屬性可以擷取到伺服器響應回來的内容。
                            // 并且不管伺服器響應回來的是什麼,都以普通文本的形勢擷取。(伺服器可能響應回來:普通文本、XML、JSON、HTML...)
                            // innerHTML屬性是javascript中的文法,和ajax的XMLHttpRequest對象無關。
                            // innerHTML可以設定元素内部的HTML代碼。(innerHTML可以将後面的内容當做一段HTML代碼解釋并執行)
                            //document.getElementById("myspan").innerHTML = this.responseText
                            document.getElementById("mydiv").innerHTML = this.responseText
                            // innerText也不是AJAX中的,是javascript中的元素屬性,和XMLHttpRequest無關。
                            // innerText也是設定元素中的内容,但是即使後面是一段HTML代碼,也是将其看做一個普通字元串設定進去。
                            //document.getElementById("myspan").innerText = this.responseText
                        }else{
                            alert(this.status)
                        }
                    }
                }
                //3. 開啟通道
                xhr.open("GET", "/ajax/ajaxrequest2", true)
                //4. 發送請求
                xhr.send()
            }
        }
    </script>
    <button id="btn">發送ajax get請求</button>
    <span id="myspan"></span>
    <div id="mydiv"></div>
    </body>
    </html>
               
  • 發送AJAX get請求,後端代碼:
    package com.bjpowernode.ajax.servlet;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @program: 代碼
     * @ClassName: AjaxRequest2Servlet
     * @version: 1.0
     * @description:
     * @author: bjpowernode
     * @create: 2022-05-13 10:46
     **/
    
    @WebServlet("/ajaxrequest2")
    public class AjaxRequest2Servlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 設定響應的内容類型以及字元集
            response.setContentType("text/html;charset=UTF-8");
            // 擷取響應流
            PrintWriter out = response.getWriter();
            // 響應
            out.print("<font color='red'>使用者名已存在!!!</font>");
        }
    }
    
               
  • AJAX get請求如何送出資料呢?
    • get請求送出資料是在“請求行”上送出,格式是:url?name=value&name=value&name=value....
    • 其實這個get請求送出資料的格式是HTTP協定中規定的,遵循協定即可。

AJAX GET請求的緩存問題

  • 對于低版本的IE浏覽器來說,AJAX的get請求可能會走緩存。存在緩存問題。對于現代的浏覽器來說,大部分浏覽器都已經不存在AJAX get緩存問題了。
  • 什麼是AJAX GET請求緩存問題呢?
    • 在HTTP協定中是這樣規定get請求的:get請求會被緩存起來。
    • 發送AJAX GET請求時,在同一個浏覽器上,前後發送的AJAX請求路徑一樣的話,對于低版本的IE來說,第二次的AJAX GET請求會走緩存,不走伺服器。
  • POST請求在HTTP協定中規定的是:POST請求不會被浏覽器緩存。
  • GET請求緩存的優缺點:
    • 優點:直接從浏覽器緩存中擷取資源,不需要從伺服器上重新加載資源,速度較快,使用者體驗好。
    • 缺點:無法實時擷取最新的伺服器資源。
  • 浏覽器什麼時候會走緩存?
    • 第一:是一個GET請求
    • 第二:請求路徑已經被浏覽器緩存過了。第二次發送請求的時候,這個路徑沒有變化,會走浏覽器緩存。
  • 如果是低版本的IE浏覽器,怎麼解決AJAX GET請求的緩存問題呢?
    • 可以在請求路徑url後面添加一個時間戳,這個時間戳是随時變化的。是以每一次發送的請求路徑都是不一樣的,這樣就不會走浏覽器的緩存問題了。
    • 可以采用時間戳:"url?t=" + new Date().getTime()
    • 或者可以通過随機數:"url?t=" + Math.random()
    • 也可以随機數+時間戳....

AJAX POST請求

  • AJAX POST請求和GET請求的代碼差別在哪裡?就是前端代碼有差別。後端代碼沒有差別。
    // 4. 發送AJAX POST請求
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") // 設定請求頭的内容類型。模拟form表單送出資料。
    // 擷取表單中的資料
    var username = document.getElementById("username").value;
    var password = document.getElementById("password").value;
    // send函數中的參數就是發送的資料,這個資料在“請求體”當中發送。
    xhr.send("username="+username+"&password="+password)
               
  • 實作一個案例:使用AJAX POST請求實作使用者注冊的時候,使用者名是否可用。(驗證使用者名是否可以注冊)實作步驟如下:
    • 在前端,使用者輸入使用者名之後,失去焦點事件blur發生,然後發送AJAX POST請求,送出使用者名
    • 在後端,接收到使用者名,連接配接資料庫,根據使用者名去表中搜尋
    • 如果使用者名已存在
      • 後端響應消息:對不起,使用者名已存在(在前端頁面以紅色字型展示)
    • 如果使用者名不存在
      • 後端響應消息:使用者名可以使用(在前端頁面以綠色字型展示)
  • 實作一個案例:使用者點選按鈕之後,發送AJAX請求,顯示學生清單。
    • 在後端java程式中拼接HTML代碼,然後将HTML代碼直接響應到浏覽器用戶端。這種方式不好,不應該在java代碼中編寫HTML代碼,能否在java程式中直接向前端響應資料?可以,可以在後端拼接JSON格式的字元串,或者XML格式的字元串,将這個字元串發送給前端,前端解析即可。

基于JSON的資料交換

  • 在WEB前端中,如何将一個json格式的字元串轉換成json對象
    var jsonStr = "{\"username\" : \"zhangsan\", \"password\" : \"1233344\"}"
    var jsonObj = JSON.parse(jsonStr)
    console.log(jsonObj.username)
    console.log(jsonObj.password)
               
  • 在後端拼接JSON格式的字元串,響應給前端的浏覽器
    json.append("[");
    while (rs.next()) {
        // 擷取每個學生的資訊
        String name = rs.getString("name");
        String age = rs.getString("age");
        String addr = rs.getString("addr");
        // 拼接json格式的字元串
        // {"name":"   王五    ","age":    20      ,"addr":"      北京大興區     "},
        json.append("{\"name\":\"");
        json.append(name);
        json.append("\",\"age\":");
        json.append(age);
        json.append(",\"addr\":\"");
        json.append(addr);
        json.append("\"},");
    }
    jsonStr = json.substring(0, json.length() - 1) + "]";
               
  • 拼接JSON格式的字元串太痛苦,可以使用阿裡巴巴的fastjson元件,它可以将java對象轉換成json格式的字元串
    List<Student> studentList = new ArrayList<>();
    while (rs.next()) {
        // 取出資料
        String name = rs.getString("name");
        int age = rs.getInt("age");
        String addr = rs.getString("addr");
        // 将以上資料封裝成Student對象
        Student s = new Student(name, age, addr);
        // 将Student對象放到List集合
        studentList.add(s);
    }
    // 将List集合轉換成json字元串
    jsonStr = JSON.toJSONString(studentList);
               
    注意:使用fastjson需要引入fastjson-1.2.2.jar

基于XML的資料交換

  • 注意:如果伺服器端響應XML的話,響應的内容類型需要寫成:
    response.setContentType("text/xml;charset=UTF-8");
               
  • xml和JSON都是常用的資料交換格式
    • XML體積大,解析麻煩。較少用。
    • JSON體積小,解析簡單,較常用。
  • 基于XML的資料交換,前端代碼
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>使用XML完成資料交換</title>
    </head>
    <body>
    <script type="text/javascript">
        window.onload = function(){
            document.getElementById("btn").onclick = function(){
                // 1.建立XMLHTTPRequest對象
                var xhr = new XMLHttpRequest();
                // 2.注冊回調函數
                xhr.onreadystatechange = function () {
                    if (this.readyState == 4) {
                        if (this.status == 200) {
                            // 伺服器端響應了一個XML字元串,這裡怎麼接收呢?
                            // 使用XMLHTTPRequest對象的responseXML屬性,接收傳回之後,可以自動封裝成document對象(文檔對象)
                            var xmlDoc = this.responseXML
                            //console.log(xmlDoc)
                            // 擷取所有的<student>元素,傳回了多個對象,應該是數組。
                            var students = xmlDoc.getElementsByTagName("student")
                            //console.log(students[0].nodeName)
                            var html = "";
                            for (var i = 0; i < students.length; i++) {
                                var student = students[i]
                                // 擷取<student>元素下的所有子元素
                                html += "<tr>"
                                html += "<td>"+(i+1)+"</td>"
                                var nameOrAge = student.childNodes
                                for (var j = 0; j < nameOrAge.length; j++) {
                                    var node = nameOrAge[j]
                                    if (node.nodeName == "name") {
                                        //console.log("name = " + node.textContent)
                                        html += "<td>"+node.textContent+"</td>"
                                    }
                                    if (node.nodeName == "age") {
                                        //console.log("age = " + node.textContent)
                                        html += "<td>"+node.textContent+"</td>"
                                    }
                                }
                                html += "</tr>"
                            }
                            document.getElementById("stutbody").innerHTML = html
                        }else{
                            alert(this.status)
                        }
                    }
                }
                // 3.開啟通道
                xhr.open("GET", "/ajax/ajaxrequest6?t=" + new Date().getTime(), true)
                // 4.發送請求
                xhr.send()
            }
        }
    </script>
    <button id="btn">顯示學生清單</button>
    <table width="500px" border="1px">
        <thead>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年齡</th>
        </tr>
        </thead>
        <tbody id="stutbody">
        <!--<tr>
            <td>1</td>
            <td>zhangsan</td>
            <td>20</td>
        </tr>
        <tr>
            <td>2</td>
            <td>lisi</td>
            <td>22</td>
        </tr>-->
        </tbody>
    </table>
    </body>
    </html>
               
  • 基于XML的資料交換,後端java程式:
    package com.bjpowernode.ajax.servlet;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @program: 代碼
     * @ClassName: AjaxRequest6Servlet
     * @version: 1.0
     * @description: 伺服器端傳回XML字元串
     * @author: bjpowernode
     * @create: 2022-05-15 11:48
     **/
    @WebServlet("/ajaxrequest6")
    public class AjaxRequest6Servlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 注意:響應的内容類型是XML。
            response.setContentType("text/xml;charset=UTF-8");
            PrintWriter out = response.getWriter();
    
            /*
            <students>
                <student>
                    <name>zhangsan</name>
                    <age>20</age>
                </student>
                <student>
                    <name>lisi</name>
                    <age>22</age>
                </student>
            </students>
             */
    
            StringBuilder xml = new StringBuilder();
            xml.append("<students>");
            xml.append("<student>");
            xml.append("<name>zhangsan</name>");
            xml.append("<age>20</age>");
            xml.append("</student>");
            xml.append("<student>");
            xml.append("<name>lisi</name>");
            xml.append("<age>22</age>");
            xml.append("</student>");
            xml.append("</students>");
    
            out.print(xml);
        }
    }
    
               

AJAX亂碼問題

  • 測試内容:
    • 發送ajax get請求
      • 發送資料到伺服器,伺服器擷取的資料是否亂碼?
      • 伺服器響應給前端的中文,會不會亂碼?
    • 發送ajax post請求
      • 發送資料到伺服器,伺服器擷取的資料是否亂碼?
      • 伺服器響應給前端的中文,會不會亂碼?
  • 包括還要測試tomcat伺服器的版本:
    • tomcat10和tomcat9都要進行測試。
  • 測試結果:
    • 對于tomcat10來說,關于字元集,我們程式員不需要幹涉,不會出現亂碼。
    • 對于tomcat9來說呢?
      • 響應中文的時候,會出現亂碼,怎麼解決?
        response.setContentType("text/html;charset=UTF-8");
                   
      • 發送ajax post請求的時候,發送給伺服器的資料,伺服器接收之後亂碼,怎麼解決?
        request.setCharacterEncoding("UTF-8");
                   

AJAX的異步與同步

  • 什麼是異步?什麼是同步?
    • ajax請求1和ajax請求2,同時并發,誰也不用等誰,這就是異步。(a不等b,b也不等a)
    • 如果ajax請求1在發送的時候需要等待ajax請求2結束之後才能發送,那麼這就是同步。(a等待b,或者b等待a,隻要發生等待,就是同步。)
  • 異步和同步在代碼上如何實作?
    // 假設這個是ajax請求1
    // 如果第三個參數是false:這個就表示“ajax請求1”不支援異步,也就是說ajax請求1發送之後,會影響其他ajax請求的發送,隻有當我這個請求結束之後,你們其他的ajax請求才能發送。
    // false表示,不支援異步。我這個請求發了之後,你們其他的請求都要靠邊站。都等着。你們别動呢,等我結束了你們再說。
    xhr1.open("請求方式", "URL", false)
    xhr1.send()
    
    // 假設這個是ajax請求2
    // 如果第三個參數是true:這個就表示“ajax請求2”支援異步請求,也就是說ajax請求2發送之後,不影響其他ajax請求的發送。
    xhr2.open("請求方式", "URL", true) 
    xhr2.send()
               
  • 什麼情況下用同步?(大部分情況下我們都是使用ajax異步方式,同步很少用。)
    • 舉一個例子
      • 使用者注冊
        • 使用者名需要發送ajax請求進行校驗
        • 郵箱位址也需要發送ajax請求校驗
        • 其他的也可能需要發送ajax請求。。。
        • 并且最終注冊按鈕的時候,也是發送ajax請求進行注冊。
        • 那麼顯然,注冊的Ajax請求和校驗的ajax請求不能異步,必須等待所有的校驗ajax請求結束之後,注冊的ajax請求才能發。

AJAX代碼封裝

  • AJAX請求相關的代碼都是類似的,有很多重複的代碼,這些重複的代碼能不能不寫,能不能封裝一個工具類。要發送ajax請求的話,就直接調用這個工具類中的相關函數即可。
  • 接下來,手動封裝一個工具類,這個工具類我們可以把它看做是一個JS的庫。我們把這個JS庫起一個名字,叫做jQuery。(我這裡封裝的jQuery隻是一個前端的庫,和後端的java沒有關系,隻是為了友善web前端代碼的編寫,提高WEB前端的開發效率)
  • 手動開發jQuery,源代碼
    function jQuery(selector){
        if (typeof selector == "string") {
            if (selector.charAt(0) == "#") {
                domObj = document.getElementById(selector.substring(1))
                return new jQuery()
            }
        }
        if (typeof selector == "function") {
            window.onload = selector
        }
        this.html = function(htmlStr){
            domObj.innerHTML = htmlStr
        }
        this.click = function(fun){
            domObj.onclick = fun
        }
        this.focus = function (fun){
            domObj.onfocus = fun
        }
        this.blur = function(fun) {
            domObj.onblur = fun
        }
        this.change = function (fun){
            domObj.onchange = fun
        }
        this.val = function(v){
            if (v == undefined) {
                return domObj.value
            }else{
                domObj.value = v
            }
        }
    
        // 靜态的方法,發送ajax請求
        /**
         * 分析:使用ajax函數發送ajax請求的時候,需要程式員給我們傳過來什麼?
         *      請求的方式(type):GET/POST
         *      請求的URL(url):url
         *      請求時送出的資料(data):data
         *      請求時發送異步請求還是同步請求(async):true表示異步,false表示同步。
         */
        jQuery.ajax = function(jsonArgs){
            // 1.
            var xhr = new XMLHttpRequest();
            // 2.
            xhr.onreadystatechange = function(){
                if (this.readyState == 4) {
                    if (this.status == 200) {
                        // 我們這個工具類在封裝的時候,先不考慮那麼多,假設伺服器傳回的都是json格式的字元串。
                        var jsonObj = JSON.parse(this.responseText)
                        // 調用函數
                        jsonArgs.success(jsonObj)
                    }
                }
            }
    
            if (jsonArgs.type.toUpperCase() == "POST") {
                // 3.
                xhr.open("POST", jsonArgs.url, jsonArgs.async)
                // 4.
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
                xhr.send(jsonArgs.data)
            }
    
            if (jsonArgs.type.toUpperCase() == "GET") {
                xhr.open("GET", jsonArgs.url + "?" + jsonArgs.data, jsonArgs.async)
                xhr.send()
            }
    
        }
    }
    $ = jQuery
    
    // 這裡有個細節,執行這個目的是為了讓靜态方法ajax生效。
    new jQuery()
    
    
               
  • 使用以上庫,怎麼用?
    <script type="text/javascript" src="/ajax/js/jQuery-1.0.0.js"></script>
    <script type="text/javascript">
        $(function(){
            $("#btn1").click(function(){
                $.ajax({
                    type : "POST",
                    url : "/ajax/ajaxrequest11",
                    data : "username=" + $("#username").val(),
                    async : true,
                    success : function(json){
                        $("#div1").html(json.uname)
                    }
                })
            })
        })
    </script>
               

AJAX實作省市關聯

  • 什麼是省市關聯?
    • 在網頁上,選擇對應的省份之後,動态的關聯出該省份對應的市。選擇對應的市之後,動态的關聯出該市對應的區。(首先要清楚需求)
  • 進行資料庫表的設計
    • t_area (區域表)
      id(PK-自增)	  code		name		pcode
      ---------------------------------------------
      1				001		 河北省		null
      2				002		 河南省		null
      3				003		 石家莊	    001
      4				004		 邯鄲			 001
      5				005		 鄭州			 002
      6				006		 洛陽			 002
      7				007		 叢台區	    004  
      
      将全國所有的省、市、區、縣等資訊都存儲到一張表當中。
      采用的存儲方式實際上是code pcode形勢。
                 
  • 建表t_area,模拟好資料。
  • 首先實作第一個功能:
    • 頁面加載完畢之後,先把省份全部展現出來。

AJAX跨域問題

跨域

  • 跨域是指從一個域名的網頁去請求另一個域名的資源。比如從百度(https://baidu.com)頁面去請求京東(https://www.jd.com)的資源。
  • 通過超連結或者form表單送出或者window.location.href的方式進行跨域是不存在問題的(大家可以編寫程式測試一下)。但在一個域名的網頁中的一段js代碼發送ajax請求去通路另一個域名中的資源,由于同源政策的存在導緻無法跨域通路,那麼ajax就存在這種跨域問題。
  • 同源政策是指一段腳本隻能讀取來自同一來源的視窗和文檔的屬性,同源就是協定、域名和端口都相同。
  • 同源政策有什麼用?如果你剛剛在網銀輸入賬号密碼,檢視了自己還有1萬塊錢,緊接着通路一些不規矩的網站,這個網站可以通路剛剛的網銀站點,并且擷取賬号密碼,那後果可想而知。是以,從安全的角度來講,同源政策是有利于保護網站資訊的。
  • 有一些情況下,我們是需要使用ajax進行跨域通路的。比如某公司的A頁面(a.bjpowernode.com)有可能需要擷取B頁面(b.bjpowernode.com)。

同源還是不同源

  • 區分同源和不同源的三要素
    • 協定
    • 域名
    • 端口
  • 協定一緻,域名一緻,端口号一緻,三個要素都一緻,才是同源,其它一律都是不同源
URL1 URL2 是否同源 描述
http://localhost:8080/a/index.html http://localhost:8080/a/first 同源 協定 域名 端口一緻
http://localhost:8080/a/index.html http://localhost:8080/b/first 同源 協定 域名 端口一緻
http://www.myweb.com:8080/a.js https://www.myweb.com:8080/b.js 不同源 協定不同
http://www.myweb.com:8080/a.js http://www.myweb.com:8081/b.js 不同源 端口不同
http://www.myweb.com/a.js http://www.myweb2.com/b.js 不同源 域名不同
http://www.myweb.com/a.js http://crm.myweb.com/b.js 不同源 子域名不同

複現AJAX跨域問題

AJAX跨域解決方案

方案1:設定響應頭

  • 核心原理:跨域通路的資源允許你跨域通路。
  • 實作:
    • response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); // 允許某個
      response.setHeader("Access-Control-Allow-Origin", "*"); // 允許所有
                 

方案2:jsonp

  • jsonp:json with padding(帶填充的json【學完之後再了解這個什麼意思!!!】)
  • jsonp不是一個真正的ajax請求。隻不過可以完成ajax的局部重新整理效果。可以說jsonp是一種類ajax請求的機制。
  • jsonp不是ajax請求,但是可以完成局部重新整理的效果,并且可以解決跨域問題。
  • 注意:jsonp解決跨域的時候,隻支援GET請求。不支援post請求。

方案3:jQuery封裝的jsonp

  • 牛人們寫的jQuery庫,已經對jsonp進行了封裝。大家可以直接拿來用。
    • $.ajax({
          type : "GET",
          url : "跨域的url",
          dataType : "jsonp", // 指定資料類型
          jsonp : "fun", // 指定參數名(不設定的時候,預設是:"callback")
          jsonpCallback : "sayHello" // 指定回調函數的名字
      							   // (不設定的時候,jQuery會自動生成一個随機的回調函數,
          						   //并且這個回調函數還會自動調用success的回調函數。)
      })
                 

方案4:代理機制(httpclient)

  • 使用Java程式怎麼去發送get/post請求呢?【GET和POST請求就是HTTP請求。】
    • 第一種方案:使用JDK内置的API(java.net.URL.....),這些API是可以發送HTTP請求的。
    • 第二種方案:使用第三方的開源元件,比如:apache的httpclient元件。(httpclient元件是開源免費的,可以直接用)
  • 在java程式中,使用httpclient元件可以發送http請求。
    • 對于httpclient元件的代碼,大家目前可以不進行深入的研究,可以從網上直接搜。然後粘貼過來,改一改,看看能不能完成發送get和post請求。
    • 使用httpclient元件,需要先将這個元件相關的jar包引入到項目當中。

方案5:nginx反向代理

  • nginx反向代理中也是使用了這種代理機制來完成AJAX的跨域,實作起來非常簡單,隻要修改一個nginx的配置即可。以後大家學習nginx之後再說吧。!!!!

AJAX實作搜尋聯想 自動補全

  • 什麼是搜尋聯想?自動補全?
    • 百度是一個很典型的代表。在百度的搜尋框中輸入相關資訊的時候,會有搜尋聯想以及自動補全。
    • 搜尋聯想和自動補全:實際上是為了友善使用者的使用。讓使用者的體驗更好。
    • 搜尋聯想:當使用者輸入一些單詞之後,自動聯想出使用者要搜尋的資訊,給一個提示。
    • 自動補全:當聯想出一些内容之後,使用者點選某個聯想的單詞,然後将這個單詞自動補全到搜尋框當中。
    • 搜尋聯想和自動補全功能,因為是頁面局部重新整理效果,是以需要使用ajax請求來完成。
  • 搜尋聯想,自動補全功能的核心實作原理?
    • 當鍵盤事件發生之後,比如:keyup:鍵彈起事件。
    • 發送ajax請求,請求中送出使用者輸入的搜尋内容,例如:北京(發送ajax請求,攜帶“北京”兩個字)
    • 後端接收到ajax請求,接收到“北京”兩個字,執行select語句進行模糊查詢。傳回查詢結果。
    • 将查詢結果封裝成json格式的字元串,将json格式的字元串響應到前端。
    • 前端接收到json格式的字元串之後,解析這個json字元串,動态展示頁面。

附錄:HTTP狀态資訊

1xx: 資訊

消息: 描述:
100 Continue 伺服器僅接收到部分請求,但是一旦伺服器并沒有拒絕該請求,用戶端應該繼續發送其餘的請求。
101 Switching Protocols 伺服器轉換協定:伺服器将遵從客戶的請求轉換到另外一種協定。

2xx: 成功

消息: 描述:
200 OK 請求成功(其後是對GET和POST請求的應答文檔。)
201 Created 請求被建立完成,同時新的資源被建立。
202 Accepted 供處理的請求已被接受,但是處理未完成。
203 Non-authoritative Information 文檔已經正常地傳回,但一些應答頭可能不正确,因為使用的是文檔的拷貝。
204 No Content 沒有新文檔。浏覽器應該繼續顯示原來的文檔。如果使用者定期地重新整理頁面,而Servlet可以确定使用者文檔足夠新,這個狀态代碼是很有用的。
205 Reset Content 沒有新文檔。但浏覽器應該重置它所顯示的内容。用來強制浏覽器清除表單輸入内容。
206 Partial Content 客戶發送了一個帶有Range頭的GET請求,伺服器完成了它。

3xx: 重定向

消息: 描述:
300 Multiple Choices 多重選擇。連結清單。使用者可以選擇某連結到達目的地。最多允許五個位址。
301 Moved Permanently 所請求的頁面已經轉移至新的url。
302 Found 所請求的頁面已經臨時轉移至新的url。
303 See Other 所請求的頁面可在别的url下被找到。
304 Not Modified 未按預期修改文檔。用戶端有緩沖的文檔并發出了一個條件性的請求(一般是提供If-Modified-Since頭表示客戶隻想比指定日期更新的文檔)。伺服器告訴客戶,原來緩沖的文檔還可以繼續使用。
305 Use Proxy 客戶請求的文檔應該通過Location頭所指明的代理伺服器提取。
306 Unused 此代碼被用于前一版本。目前已不再使用,但是代碼依然被保留。
307 Temporary Redirect 被請求的頁面已經臨時移至新的url。

4xx: 用戶端錯誤

消息: 描述:
400 Bad Request 伺服器未能了解請求。
401 Unauthorized 被請求的頁面需要使用者名和密碼。
402 Payment Required 此代碼尚無法使用。
403 Forbidden 對被請求頁面的通路被禁止。
404 Not Found 伺服器無法找到被請求的頁面。
405 Method Not Allowed 請求中指定的方法不被允許。
406 Not Acceptable 伺服器生成的響應無法被用戶端所接受。
407 Proxy Authentication Required 使用者必須首先使用代理伺服器進行驗證,這樣請求才會被處理。
408 Request Timeout 請求超出了伺服器的等待時間。
409 Conflict 由于沖突,請求無法被完成。
410 Gone 被請求的頁面不可用。
411 Length Required "Content-Length" 未被定義。如果無此内容,伺服器不會接受請求。
412 Precondition Failed 請求中的前提條件被伺服器評估為失敗。
413 Request Entity Too Large 由于所請求的實體的太大,伺服器不會接受請求。
414 Request-url Too Long 由于url太長,伺服器不會接受請求。當post請求被轉換為帶有很長的查詢資訊的get請求時,就會發生這種情況。
415 Unsupported Media Type 由于媒介類型不被支援,伺服器不會接受請求。
416 伺服器不能滿足客戶在請求中指定的Range頭。
417 Expectation Failed

5xx: 伺服器錯誤

消息: 描述:
500 Internal Server Error 請求未完成。伺服器遇到不可預知的情況。
501 Not Implemented 請求未完成。伺服器不支援所請求的功能。
502 Bad Gateway 請求未完成。伺服器從上遊伺服器收到一個無效的響應。
503 Service Unavailable 請求未完成。伺服器臨時過載或當機。
504 Gateway Timeout 網關逾時。
505 HTTP Version Not Supported 伺服器不支援請求中指明的HTTP協定版本。