Ajax學習筆記


Ajax學習筆記

已完結,請放心食用~

全局刷新和局部刷新

01 全局刷新

整個瀏覽器被新的數據覆蓋,在網絡中傳輸大量的數據,瀏覽器需要加載,渲染頁面

02 局部刷新

在瀏覽器的內部,發起請求,獲取數據,改變頁面中的部分內容

局部刷新的速度更快,可以按需獲取數據

ajax是用來做局部刷新的,局部刷新使用的核心對象是 異步對象(XMLHttpRequest)

這個異步對象是存在瀏覽器內存中的,使用javascript語法創建和使用 XMLHttpRequest 對象

Ajax概念

  • Asynchronous Javascript and XML(異步的 Javascript 和 XML)

    • Asynchronous:異步
      • 同步只能處理一個請求
      • 異步可以分開處理多個請求
    • Javascript:Javascript腳本,在瀏覽器中執行
    • and:和
    • xml:是一種數據格式
  • 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
      • image-20210823211726467
      • image-20210823212153507
      • image-20210823212504522
      • image-20210823212956777
      • 最后打開 tomcat \ bin \ tomcat.exe 啟動服務
      • 不然會出大問題!(tomcat服務更新異常,無法更新或更新不完全)
    • (3)創建 jsp 結果頁面
      • web 目錄下創建 jsp 頁面,以便實現 index.jsp(首頁)到 result.jsp 的跳轉
  • 第三步:編寫服務器端

    • (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 會出現下圖描述的報錯

        • image-20210823210244571

    • (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,只需要設置:
      • image-20210823212504522
  • 第三步:編寫服務器端

    • (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>
        
      • s1
      • s2
      • s3
      • sz
      • 服務器端是空數據,但整個流程步驟完成執行,所以狀態碼變化為 0 => 1 => 2 => 4(0看不到)

    • 重寫服務器端 Version 3.0

      • 在 index.jsp 加上狀態碼,觀察其變化

      • // 2.綁定事件
        xmlHttp.onreadystatechange = function (){
        	// 處理服務器端返回的數據,更新當前頁面
        	alert("readyState屬性值====" + xmlHttp.readyState + 
        	" | status:" + xmlHttp.status);
        }
        
      • image-20210825092740212
      • image-20210825092728518
      • image-20210825092802164
      • image-20210825092825561
    • 重寫服務器端 Version 4.0

      • 目的:觀察異步對象發起請求過程中完整的狀態變化

      • 更改對象:myServlet.java

      • // 寫在doGet()方法中
        System.out.println("接受了Ajax的請求");
                
        PrintWriter pw = response.getWriter();
        pw.println("Hello,Ajax!");
        pw.flush();
        pw.close();
        
      • image-20210825093351764
      • image-20210825093418504
      • image-20210825093438424
      • image-20210825093450834
    • 重寫服務器端 Version 5.0

      • 目的:觀察異步對象發起請求過程中完整的狀態變化

      • 更改對象:index.jsp

      • // 2.綁定事件
        xmlHttp.onreadystatechange = function (){
        	// 處理服務器端返回的數據,更新當前頁面
        	if( xmlHttp.readyState == 4 && xmlHttp.status == 200 ){
        		alert(xmlHttp.responseText);
        	}
        }
        
      • image-20210825094120617
      • 點擊按鈕彈窗后,數據並未發生變化

        • image-20210825094228840
        • 按鈕中有一個異步對象xmlHttp,該異步對象發起請求
        • 把數據給Servlet,Servlet又把數據給了異步對象xmlHttp
        • image-20210825095634154
    • 重寫服務器端 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);
        
      • image-20210825101019639
    • 重寫服務器端 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();
        
      • image-20210825102140105
    • 重寫服務器端 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 文件夾中
    • image-20210825151427647
    • 前綴 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,只需要設置:
      • image-20210823212504522
  • 第三步:編寫服務器端

    • 搭建服務器端的基本結構

      • 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寫完之后測一下

      • img
    • 編寫 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的數據,返回后才可以繼續使用,但異步可以同時處理多個請求

不會妨礙其他代碼的執行

同步的方式,在任意時刻只能執行一個請求


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM