zoukankan      html  css  js  c++  java
  • AJAX

    BS通信模型

      B/S 结构项目中, 浏览器(Browse)负责把用户的请求和参数通过网络发送给服务器(Server)。

      服务端使用 Servlet(多种服务端技术的一种)接收请求,并将处理结果返回给浏览器。
      浏览器在 html,jsp 上呈现数据,混合使用 css, js 帮助美化页面,或响应事件。


     1.0-全局刷新 和 局部刷新

      全局刷新 整个浏览器被新的数据覆盖。 在网络中传输大量的数据。 浏览器需要加载,渲染页面。

      全局刷新原理:

            1) 必须由浏览器亲自向服务端发送请求协议包。
            2) 这个行为导致服务端直接将【响应包】发送到浏览器内存中
            3) 这个行为导致浏览器内存中原有内容被覆盖掉
            4) 这个行为导致浏览器在展示数据时候,只有响应数据可以展示

      局部刷新 在浏览器的内部,发起请求,获取数据,只改变页面中的部分内容。 其余的页面无需加载和渲染。在网络中数据传输量少, 用户体验效果好。

           (浏览器在展示数据时,此时在窗口既可以看到本次的响应数据, 同时又可以看到浏览器内存中原有数据) 

      局部刷新原理:
            1) 不能由浏览器发送请求给服务端
            2) 浏览器委托浏览器内存中一个脚本对象代替浏览器发送请求.
            3) 这个行为导致导致服务端直接将【响应包】发送脚本对象内存中
            4) 这个行为导致脚本对象内容被覆盖掉,但是此时浏览器内存中绝大部分内容没有收到任何影响.
            5) 这个行为导致浏览器在展示数据时候,同时展示原有数据和响应数据


     2.0-AJAX技术概述

    全称:"Asynchronous JavaScript and XML"    "异步的 JavaScript 和 XML"

    作用:使用Ajax技术实现局部刷新的功能效果。

    原理:通过使用JavaScript 语法创建异步对象 XMLHttpRequest ,并操作 异步对象,向服务器发送请求 或 从获取服务端发送来的XML或JSON格式的数据, 更新页面的dom对象,最后在浏览器中进行解析展示。

    说明:ajax请求的目的是需要获取服务器端的数据。

      1)AJAX是在 2005年被Jesse James Garrett提出的新术语,用来描述一种使用现有技术集合混合使用的一种‘新’方法。而并非一门编程语言。 是一种在无需重新加载整个网页的情况下,能够更新部分页面内容(局部更新 )的新方法。AJAX 不仅需要前端的技术,同时需要后端(服务器)的配合。服务器需要提供数据,数据是 AJAX 请求的响应结果。

      2)ajax包含的技术主要包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。 核心是javascript 和 xml 。        

         浏览器内建的 XMLHttpRequest 对象  :   ( 负责 从 web 服务器发送请求, 接收响应数据

         JavaScript 和 HTML、 DOM :                 (负责显示或使用数据)

         XML: 是一种在网络中的传输的数据格式。(负责发送和接收的数据格式,现在主流使用 json数据传输格式)

      3)局部刷新使用的核心对象是 XMLHttpRequest【异步对象】。(由该对象负责局部刷新)

      4)异步对象使用JavaScript语法进行创建和使用,异步对象存在于浏览器内存中。

      5)浏览器内存中可以存在多个异步对象。每一个异步对象都可以独自向服务器发送请求,和 从服务器中获取数据。

      6)使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作。


    百度百科》

      1)Ajax这个术语源自描述从基于 Web 的应用到基于数据的应用。

      2)Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。

      3)使用 JavaScript 向服务器提出请求并处理响应而不阻塞用户核心对象XMLHttpRequest。通过这个对象,您的 JavaScript 可在不重载页面的情况与 Web 服务器交换数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效果。
      4)Ajax 在浏览器与 Web 服务器之间使用异步数据传输(HTTP 请求),这样就可使网页从服务器请求少量的信息,而不是整个页面。
     
      5)Ajax可使因特网应用程序更小、更快,更友好。
      6)Ajax 是一种独立于 Web 服务器软件的浏览器技术。 
      7)Ajax 基于下列 Web 标准:
        JavaScript、XML、HTMLCSS 在 Ajax 中使用的 Web 标准已被良好定义,并被所有的主流浏览器支持。
        Ajax 应用程序独立于浏览器和平台。
        Web 应用程序较桌面应用程序有诸多优势;它们能够涉及广大的用户,它们更易安装及维护,也更易开发。
        不过,因特网应用程序并不像传统的桌面应用程序那样完善且友好。通过 Ajax,因特网应用程序可以变得更完善,更友好。
                                                      

    2.1-AJAX的工作流程

    1. 网页中发生一个事件(页面加载、按钮点击)
    2. 由 JavaScript 创建 XMLHttpRequest 对象
    3. XMLHttpRequest 对象向 web 服务器发送请求
    4. 服务器处理该请求
    5. 服务器将响应发送回网页
    6. 由 JavaScript 读取响应
    7. 由 JavaScript 执行正确的动作(比如更新页面)

    3.0-XMLHttpRequest 异步对象概述

    概 述

      在局部刷新,需要创建一个对象,代替浏览器发起请求的行为,这个对象存在内存中。
      代替浏览器发起请求并接收响应数据。这个对象叫做异步请求对象。
      全局刷新是同步行为 [浏览器数据会全部更新] 局部刷新是异步行为 [浏览器数据没有全部更新]
      这个异步对象用于在后台与服务器交换数据。XMLHttpRequest 就是我们说的异步对象。

      1)-所有现代的浏览器都支持 XMLHttpRequest 对象。

      2)-XMLHttpRequest 对象用于在后台与服务器交换数据。

      3)-XMLHttpRequest 对象的作用:

    • 在不重新加载页面的情况下更新网页;
    • 在页面已加载后从服务器请求数据;
    • 在页面已加载后从服务器接收数据;
    • 在后台向服务器发送数据; 

    详细教程:https://www.w3school.com.cn/xml/xml_http.asp


    3.1-XMLHttpRequest 异步对象的属性

    readyState属性

    ———— 表示异步对象请求的状态变化  (有0~4 五个值)

      0: 创建异步对象, 执行new XMLHttpRequest();时。

      1:   初始异步请求对象, 执行xmlHttpRequest.open( );时。

      2: 发送请求, 执行xmlHttpRequest.send();时。

      3:   从服务器端获取了数据,此时是3。 注意3是异步对象内部使用, 表示获取了原始的数据。(开发人员一般不用3这个值)

      4:异步对象把接收的数据处理完成后。 此时开发人员在状态值是4的时候来处理数据。(在4状态时候,开发人员应该做什么 ?—— 拿到数据之后,更新当前页面。)

    status属性

    ———— 表示网络请求的状况的。

      200,当status==200时,表示网络请求是成功的。

      404,当status==404时,表示请求访问不到服务器资源。

      500,当status==500时,表示服务器代码出错。

     responseText属性

    ———— 获取服务器端返回获的字符串形式的响应数据。

        var data = xmlHttpRequest.responseText; 

     responseXML属性

    ———— 获得 XML 形式的响应数据。

        var data = xmlHttpRequest.responseXML;


    3.2-使用XMLHttpRequest对象的步骤

    1) 创建异步对象

    // 1)-创建异步对象
    var
    xmlHttp = new XMLHttpRequest();

    2) 给异步对象绑定 onreadystatechange 事件

      onreadystatechange 是一个事件句柄。它的值 (state_Change) 是一个函数的名称,当 XMLHttpRequest 对象的状态发生改变时,会触发此函数。

      状态从 0 (uninitialized) 到 4 (complete) 进行变化。仅在状态为 4 时,我们才执行代码。

      需要为这个事件指定一个函数, 在函数中处理状态的变化。当异步对象发起请求 或 获取了数据都会触发这个事件。

      通过该事件可以获取异步对象发送请求或获取数据的状态。

    // 2)-为异步对象绑定onreadystatechange事件,处理请求的状态变化。
    xmlHttpRequest.onreadystatechange= function(){     
    }

    3) 初始异步请求对象

    ———xmlHttpRequest.open( String method,String url,boolean async);

    // 3)-初始异步请求对象。采用get提交方式,访问loginServlet且携带相关的参数
    xmlHttpRequest.open("get", "loginServlet?name=james&pwd=123",true);

      method参数:请求的类型;GET 或 POST

      url参数:        服务器端的访问地址。可以携带相关的参数。

      async参数:  true(异步)或 false(同步)。该参数规定请求是否异步处理。默认的true值代表异步请求,false值表示同步请求。

          异步处理请求: 使用异步对象发起请求之后,脚本会在 send() 方法之后继续执行,而不等待来自服务器的响应。即不用等待数据处理完毕,就可以执行其他操作。

         同步处理请求:异步对象必须处理完成请求,从服务端获取数据后,才能执行send()之后的代码。任意时刻只能执行一个请求。onreadystatechange 事件使代码复杂化了。但是这是在没有得到服务器响应的情况下,防止代码停止的最安全的方法。通过把该参数设置为 "false",可省去额外的onreadystatechange代码。若在请求失败时是否执行其余的代码无关紧要,则么可以使用该参数。

    4) 使用异步对象发送请求

    // 4)-异步对象向服务器发送请求 
    xmlHttpRequest.send( );

    5) 接收并处理服务端的数据

    如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或responseXML 属性。
        responseText:获得字符串形式的响应数据
        responseXML:获得 XML 形式的响应数据

    需要注意的是:第5步中的代码需要写在第2步之中。

    // 2)-为异步对象绑定onreadystatechange事件,处理请求的状态变化。
    xmlHttpRequest.onreadystatechange= function(){    
    
                 //5)-【处理服务器端的数据,更新当前页面】
                //异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态。
        if(xmlHttpRequest.readyState == 4 && xmlHttpRequest.status== 200 ){ 
         
        
          //获取到的是服务端发送来的数据。
         var data = xmlHttpRequest.responseText;         
    
         //更新页面DOM对象的内容。   
        document.getElementById("name").value= data; 
      }    
        
    }            

     提出问题:为何处理数据放在第二步?异步对象涉及到回调函数

      当第四步的send()方法执行之后,将会等待服务端返回数据。服务端数据返回之后,还会执行第二步中的代码(根据判断条件来处理数据)。

      每当请求的状态变化时,异步对象就会自动调用一次onreadystatechange事件对应的函数。


    4.1-全局刷新案例:计算用户BMI值

    方案1 借助请求域空间进行存储处理数据)

    代码思路:BmiServlet的处理数据,借助请求域空间进行存储。并且请求转发到result.jsp页面中,向用户进行数据展示。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>全局刷新计算BMI</title>
      </head>
      <body>
      <p>全局刷新计算BMI</p>
      <form action="bmiServlet" method="post">
        姓名:<input type="text" name="name"/><br/>
        身高:<input type="text" name="height"/>(M)<br/>
        体重:<input type="text" name="weight"/>(KG)<br/>
        <input type="submit" value="计算BMI值" >
      </form>
      </body>
    </html>
    index.jsp
     1 package com.penguin1024.controller;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.http.HttpServlet;
     5 import javax.servlet.http.HttpServletRequest;
     6 import javax.servlet.http.HttpServletResponse;
     7 import java.io.IOException;
     8 
     9 public class BmiServlet extends HttpServlet {
    10     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    11         // 覆盖此请求体中使用的字符编码的名称。(解决post提交产生的中文请求参数问题)
    12         request.setCharacterEncoding("utf-8");
    13 
    14         // 获取用户提交的请求参数信息
    15         String nameStr = request.getParameter("name");
    16         String heightStr = request.getParameter("height");
    17         String weightStr = request.getParameter("weight");
    18 
    19         // 需要先将字符串类型的heightStr 和  weightStr ,转为float类型。
    20         Float height = Float.valueOf(heightStr);
    21         Float weight = Float.valueOf(weightStr);
    22 
    23         // 再按照公式计算BMI值。  体质指数(BMI)=体重(千克)除以身高(平方米)
    24         Float bmi = weight/(height*height);
    25 
    26 
    27         // 准备一个空字符串,用于提示用户信息。
    28         String msg = "";
    29         // 计算用户BMI值所对应的范围
    30         if( bmi <= 18.5) {
    31             msg = "您比较瘦";
    32         } else if( bmi > 18.5 && bmi <= 23.9 ){
    33             msg = "您的bmi是正常的";
    34         } else if( bmi >24 && bmi <=27){
    35             msg = "您的身体比较胖";
    36         } else {
    37             msg = "您的身体肥胖";
    38         }
    39 
    40         // 拼接字符串提示信息
    41         msg = nameStr + "先生/女士。 您的BMI值是:"+ bmi + " ———— "+ msg;
    42 
    43         // 将字符串类型msg变量,存储到request域中。(用于让对应的jsp页面使用EL表达式获取,并展示数据给用户)
    44         request.setAttribute("msg",msg);
    45 
    46         // 请求转发到result.jsp页面中
    47         request.getRequestDispatcher("/result.jsp").forward(request,response);
    48     }
    49 
    50     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    51         this.doPost(request,response);
    52     }
    53 }
    com.penguin1024.controller.BmiServlet
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>BMI结果界面</title>
    </head>
    <body>
        <p>显示bmi计算结果</p>
        <h3>${msg}</h3>
    </body>
    </html>
    result.jsp

    方案2 (借助标准输出流对象,将提示信息输出到浏览器)

    代码思路:BmiPrintServlet不借助域空间存储数据,直接借助标准输出流对象,将提示信息输出到浏览器。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>全局刷新计算BMI</title>
      </head>
      <body>
      <p>全局刷新计算BMI</p>
      <form action="bmiPrintServlet" method="post">
        姓名:<input type="text" name="name"/><br/>
        身高:<input type="text" name="height"/>(M)<br/>
        体重:<input type="text" name="weight"/>(KG)<br/>
        <input type="submit" value="计算BMI值" >
      </form>
      </body>
    </html>
    index.jsp
     1 package com.penguin1024.controller;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.http.HttpServlet;
     5 import javax.servlet.http.HttpServletRequest;
     6 import javax.servlet.http.HttpServletResponse;
     7 import java.io.IOException;
     8 import java.io.PrintWriter;
     9 
    10 public class BmiPrintServlet extends HttpServlet {
    11     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    12         // 覆盖此请求体中使用的字符编码的名称。(解决post提交产生的中文请求参数问题)
    13         request.setCharacterEncoding("utf-8");
    14 
    15         // 获取用户提交的请求参数信息
    16         String nameStr = request.getParameter("name");
    17         String heightStr = request.getParameter("height");
    18         String weightStr = request.getParameter("weight");
    19 
    20         // 需要先将字符串类型的heightStr 和  weightStr ,转为float类型。
    21         Float height = Float.valueOf(heightStr);
    22         Float weight = Float.valueOf(weightStr);
    23 
    24         // 再按照公式计算BMI值。  体质指数(BMI)=体重(千克)除以身高(平方米)
    25         Float bmi = weight/(height*height);
    26 
    27 
    28         // 准备一个空字符串,用于提示用户信息。
    29         String msg = "";
    30         // 计算用户BMI值所对应的范围
    31         if( bmi <= 18.5) {
    32             msg = "您比较瘦";
    33         } else if( bmi > 18.5 && bmi <= 23.9 ){
    34             msg = "您的bmi是正常的";
    35         } else if( bmi >24 && bmi <=27){
    36             msg = "您的身体比较胖";
    37         } else {
    38             msg = "您的身体肥胖";
    39         }
    40 
    41         // 拼接字符串提示信息
    42         msg = nameStr + "先生/女士。 您的BMI值是:"+ bmi + " ———— "+ msg;
    43 
    44 
    45         // 如果尚未提交响应,则设置发送到客户机的响应的内容类型 
    46         // 且将发送到客户端的响应的字符编码(MIME字符集)设置为UTF-8。
    47         // 能解决响应中的中文乱码问题。
    48         response.setContentType("text/html;charset=utf-8");
    49 
    50         // 获取标准输出流对象,该对象可以向客户端发送字符文本。
    51         PrintWriter out = response.getWriter();
    52         // 输出数据
    53         out.println(msg);
    54         // 清空缓存
    55         out.flush();
    56         // 关闭流
    57         out.close();
    58         
    59     }
    60 
    61     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    62         this.doPost(request,response);
    63     }
    64 }
    BmiPrintServlet

    访问:


     4.2-Ajax局部刷新案例:计算用户BMI值

    使用ajax技术实现局部刷新功能效果的代码思路

    1-新建index.jsp,创建和使用XMLHttpRequest异步对象。(5个步骤)
        1).创建
        2).绑定事件
        3).初始请求
        4).发送请求
           5).处理服务端发送的数据 
    2-创建服务器的BmiAjaxServlet.java,接收并处理来自异步对象发送的请求数据, 并把处理之后的数据通过标准输出流输出给异步对象。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>Ajax局部刷新计算BMI</title>
    
        <script type="text/javascript">
    
          // 使用浏览器内存中的异步对象,代替浏览器发起请求。异步对象使用js创建和管理的。
          function doAjax() {
            // 1-创建异步请求对象
            var xmlHttpRequest=  new XMLHttpRequest();
    
            // 2-绑定onreadystatechange事件
            xmlHttpRequest.onreadystatechange = function () {
    
              //异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态。
              if (xmlHttpRequest.readyState==4 && xmlHttpRequest.status ==200){
    
                // 获取服务器发送来的数据
                var data = xmlHttpRequest.responseText;
                // 更新dom对象,更新页面数据
                document.getElementById("mydata").innerText = data;
    
              }
    
            }
            // 3-初始异步请求对象 (初始化请求数据)
    
            // 获取dom对象的value值
            var name = document.getElementById("name").value;
            var height = document.getElementById("height").value;
            var weight = document.getElementById("weight").value;
    
    
            // JavaScript 中的encodeURI(String uri) 函数作用:可把字符串作为 URI 进行编码。
            // JavaScript 中的decodeURI(String uri) 函数作用:可对encodeURI(String uri) 编码过的 URI 进行解码。
            name = encodeURI(name);
            alert(name); // 结果是 %E8%83%96%E4%BC%81%E9%B9%85
    
            // 按照格式拼接需要携带的请求参数
            var parameter = "name="+name+"&height="+height+"&weight="+weight;
            xmlHttpRequest.open("get","${pageContext.request.contextPath}/bmiAjaxServlet?"+parameter,true)
    
            // 4-向服务器发送请求
            xmlHttpRequest.send();
    
          }
          
        </script>
    
      </head>
      <body>
      <p>局部刷新ajax-计算bmi</p>
      <div>
        <!-- ajax局部刷新没有使用<form>提交  -->
        姓名:<input type="text" id="name" /> <br/>
        身高:<input type="text" id="height" /> <br/>
        体重:<input type="text" id="weight" /> <br/>
        <input type="button" value="计算bmi" onclick="doAjax()">
        <br/>
        <br/>
        <div id="mydata">等待加载数据....</div>
      </div>
    
      </body>
    </html>
    index.jsp
    package com.penguin1024.controller;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class BmiAjaxServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 覆盖此请求体中使用的字符编码的名称。(解决post提交产生的中文请求参数问题)
            request.setCharacterEncoding("utf-8");
    
            // 获取用户提交的请求参数信息
            String nameStr = request.getParameter("name");
            String heightStr = request.getParameter("height");
            String weightStr = request.getParameter("weight");
    
            // 需要先将字符串类型的heightStr 和  weightStr ,转为float类型。
            Float height = Float.valueOf(heightStr);
            Float weight = Float.valueOf(weightStr);
    
            // 再按照公式计算BMI值。  体质指数(BMI)=体重(千克)除以身高(平方米)
            Float bmi = weight/(height*height);
    
    
            // 准备一个空字符串,用于提示用户信息。
            String msg = "";
            // 计算用户BMI值所对应的范围
            if( bmi <= 18.5) {
                msg = "您比较瘦";
            } else if( bmi > 18.5 && bmi <= 23.9 ){
                msg = "您的bmi是正常的";
            } else if( bmi >24 && bmi <=27){
                msg = "您的身体比较胖";
            } else {
                msg = "您的身体肥胖";
            }
    
            // 拼接字符串提示信息
            msg = nameStr + "先生/女士。 您的BMI值是:"+ bmi + " ———— "+ msg;
    
            // 如果尚未提交响应,则设置发送到客户机的响应的内容类型
            // 且将发送到客户端的响应的字符编码(MIME字符集)设置为UTF-8。
            // 能解决响应中的中文乱码问题。
            response.setContentType("text/html;charset=utf-8");
    
            // 获取标准输出流对象,该对象可以向客户端发送字符文本。
            PrintWriter out = response.getWriter();
            // 输出数据 (响应ajax需要的数据,使用HttpServletResponse输出数据)
            out.println(msg);
            // 清空缓存
            out.flush();
            // 关闭流
            out.close();
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }
    BmiAjaxServlet.java

     JS代码中的中文请求参数的传输问题?

    JavaScript 中的encodeURI(String uri) 函数:可把字符串作为 URI 进行编码。

    JavaScript 中的decodeURI(String uri) 函数:可对encodeURI(String uri) 编码过的 URI 进行解码。

     如:alert(encodeURI("胖企鹅"));    的执行结果是 E88396E4BC81E9B985


     4.3-Ajax局部刷新案例:根据省份id获取省份名称,并局部更新界面信息。

    1-环境搭建

    0)-DOS命令行窗口mysql中文显示乱码问题解决方法:

     产生原因:MySQL的默认编码是Latin1,不支持中文,因此需要修改MySQL的默认编码。只需修改mysql安装目录下的my.ini 配置文件的两处地方即可:

     

    1)-创建数据库 fatpenguin

    create database fatpenguin;

    2)-使用创建好的数据库,并在该数据库中添加两张表:province (省份信息表)  

    use fatpenguin;

    province省份表:

    CREATE TABLE `province` (
     `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;

    3)-查看province表中的数据

    4)-创建javaweb项目  

      在web/WEB-INF目录下手动创建lib目录 和 classes目录。并在lib目录中放置mysql的驱动jar包并打开 Project Structure 进行相关的工程结构设置 。       (参照IDEA设置博客)

    2-编写代码

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>ajax根据省份id获取名称</title>
    
        <script type="text/javascript">
          // 使用浏览器内存中的异步对象,代替浏览器发起ajax请求,传递参数给服务器, 服务器返回数据。
    
          //1.创建异步对象 (异步对象使用js创建和管理的。)
          function search() {
            // 1-创建异步请求对象
            var xmlHttpRequest=  new XMLHttpRequest();
    
            // 2-绑定onreadystatechange事件
            xmlHttpRequest.onreadystatechange = function () {
    
              // 5-对从服务端中返回的数据做相关处理
    
              // 判断:若 异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态的情况下。
              if (xmlHttpRequest.readyState==4 && xmlHttpRequest.status ==200){
    
                // 获取服务器发送来的数据
                var data = xmlHttpRequest.responseText;
                // 更新dom对象,更新页面数据
                document.getElementById("proname").value = data;
    
              }
    
            }
            // 3-初始异步请求对象 (初始化请求数据)
    
            //获取proid文本框的值 (用户在界面中输入的值)
            var proid = document.getElementById("proid").value;
    
            // 使用js中的函数encodeURI(String uri) 对字符串 进行编码  (可以解决JS中的中文参数乱码问题)
            proid = encodeURI(proid); 
    
            xmlHttpRequest.open("get","${pageContext.request.contextPath}/queryProviceServlet?proid="+proid,true);
    
            // 4-向服务器发送请求
            xmlHttpRequest.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>
    
    index.jsp
    index.jsp
    package com.penguin1024.utils;
    import java.sql.*;
    // 定义连接数据库的JDBC工具类
    // 注意事项:工具类中的 可能产生异常的代码 不使用try..catch方式处理,一般使用抛出的方式。
    // 因为使用try...catch方式进行处理。代码一旦发生异常,工具类的调用者不好定位到发生异常的代码。
    public class JdbcUtil {
    
        // 静态代码块
        static {
            try {
                // 1-在JdbcUtil类加载时,加载mysql数据库的驱动
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        // 声明一个成员变量Connection对象 ,且需定义为静态成员  (该代码由下列方法中的代码思考之后,添加的)
        // 静态方法中只能访问静态成员,不能访问到实例成员。
        static Connection conn = null;
    
    
        // 2-定义:获取数据库连接Connection对象的方法
        // 注意:Connection 是java.sal.Connection(接口)。为什么? —— 面向接口编程,好处是不用在乎该连接是由谁实现的
        public static Connection getConnection() throws SQLException {
    
            String user = "jdbc:mysql://localhost:3306/fatpenguin";
            String url = "root";
            String password = "111";
    
            //重点注意:
            //思考什么时候需要创建Connection接口对象?每次使用时候都需要创建新的连接吗?
            //当conn = null时,才需要创建一个新的Connection接口对象。
    
    
            // Connection conn = null;错误。不能在此处将conn变量定义为局部变量。
            // 这样的写的话,下面的判断结果永远是false值。
            // 因此需要将在类中定义为静态成员: private static Connection conn = null;
    
            // conn值为null,或conn被关闭时,需要重新创建Connection对象。
            
            // 如果Connection对象为null,或者Connection对象已经被关闭掉的情况下
            if (conn == null || conn.isClosed()  ){
                // 满足以上条件,则创建新的Connection对象。
                conn = DriverManager.getConnection(user, url, password);
            }
            return conn;
        }
    
        // 3-定义:关闭相关资源
        public static void close(Connection conn, Statement stmt, ResultSet rs) throws SQLException {
            // 关闭资源1
            // 如果conn不等于null,且conn也没有被关闭的情况下。
            if (conn != null && !conn.isClosed()) {
                conn.close(); // 关闭
            }
    
            // 关闭资源2
            if (stmt != null && !conn.isClosed()) {
                stmt.close(); // 关闭
            }
    
            // 关闭资源3
            if (rs != null && !conn.isClosed()) {
                rs.close(); // 关闭
            }
        }
    }
    JdbcUtil.java
    JdbcUtil.java
    package com.penguin1024.dao;
    import com.penguin1024.utils.JdbcUtil;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    // 对数据库中的数据执行相关的操作
    public class ProvinceDao {
        // 根据用户输入的省份id,查询出该id值所对应的省份名称
        public String queryProvinceNameById(Integer provinceid){
    
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet res = null;
    
            // 定义一个空字符串,用于接收查询出来的省份名称
            String name = "";
    
            try {
                 // 1-借助编写好的JdbcUtil工具类,获取Connection 数据库连接对象
                 conn = JdbcUtil.getConnection();
    
                 // 2-编写SQL语句框架
                 String sql = "select name from province where id = ?";
    
                 // 3-对SQL语句框架进行预编译处理 (避免SQL注入情况的产生)
                 ps = conn.prepareStatement(sql);
    
                 // 4-对SQL语句框架中的占位符,设置具体的参数值
                ps.setInt(1,provinceid);
    
                // 5-执行SQL语句,并接收返回的结果集
                 res = ps.executeQuery();
    
                 // 6-遍历处理查询结果集
                 while (res.next()){
                     // 获取这条数据中,字段名为"name"的值
                      name = res.getString("name");
                 }
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
    
                try {
                    // 7-借助编写好的JdbcUtil工具类,关闭相关资源
                    JdbcUtil.close(conn,ps,res);
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
    
    
            // 8-返回省份id编号所对应的省份名称
            return  name;
        }
    
    }
    
    ProvinceDao.java
    ProvinceDao.java
    package com.penguin1024.controller;
    
    import com.penguin1024.dao.ProvinceDao;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    // 执行相关的业务逻辑操作
    public class QueryProviceServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            // 定义一个字符串类型变量,用于接收查询到的省份名称。
            String provinceName ="默认没有数据";
    
            // 1-对请求参数做相关处理
            // 覆盖此请求体中使用的字符编码的名称。 (解决post方式的中文乱码问题)
            request.setCharacterEncoding("utf-8");
            // 接收来自Ajax异步对象发送来的请求参数
            String proidStr = request.getParameter("proid");
            // 将字符串类型的省份id编号,转换为Integet类型
            Integer provinceId = Integer.valueOf(proidStr);
    
            // 2-访问Dao层对象,从数据库中查询数据
    
            // 判断条件:
            // 用户在查询界面中输入的不是空字符串
            // 且输入的id编号在转换为Integer类型之后的值不为null
            // 且转换为Integer类型的结果是在[1-9]区间的整数
            if(  !"".equals(proidStr.trim()) && provinceId != null && (provinceId>=1 && provinceId<=9)) {
                // 创建dao对象
                ProvinceDao dao = new ProvinceDao();
    
                //  调用dao对象的方法 — —根据用户添加的省份id编号,到数据库中查找出该编号对应的省份名称
                 provinceName = dao.queryProvinceNameById(provinceId);
            }else {
                provinceName = "请输入合法的省份编号!!!";
            }
    
            // 3-向发送请求的Ajax异步请求对象返回查询到的结果
    
            //使用HttpServletResponse输出数据
            // servlet返回给浏览器的是文本数据类型, 告诉浏览器采用utf-8字符集进行解码 (解决响应的中文乱码问题)
            response.setContentType("text/html;charset=utf-8");
    
            // 获取标准输出流
            PrintWriter out = response.getWriter();
    
            // 往标准输出流中写入的数据,会被响应到发出相应请求的Ajax异步对象中。
            out.println(provinceName);
    
            // 清空缓存
            out.flush();
    
            // 关闭流
            out.close();
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }
    QueryProviceServlet.java

    注意事项:

      1)index.jsp的编写步骤:最先编写登录界面的前端显示内容(body标签中的内容),再搭建好Ajax代码的1-4步代码。  Ajax代码中的第5步骤代码留在最后编写,也就是编写完QueryProviceServlet.java代码之后再进行编写。

      2)mysql建表语句中问题:

        Mysql中如果表和表之间建立的外键约束,则无法删除表及修改表结构。
        解决方法:在Mysql中取消外键约束:  添加代码 SET FOREIGN_KEY_CHECKS=0;  然后将原来表的数据导出到sql语句,重新创建此表后,再把数据使用sql导入,然后再设置外键约束:SET FOREIGN_KEY_CHECKS=1;  

    3-测试查询结果

    输入合法的1-9的整数编号值,显示结果如下

                                              

    若输入1-9之外的整数值,显示结果如下:

                                             

     若在省份编号栏中,输入空字符串 或 中文,则程序会报500错误。(程序抛出异常)

                                             


    4.4-Ajax局部刷新案例:根据省份id获取省份信息,并局部更新界面信息。

    1-环境搭建

    1)创建javaweb项目。

    操作:

      在web/WEB-INF目录下手动创建lib目录 和 classes目录。并在lib目录中并添加mysql驱动 以及 json相关的jar包,并打开 Project Structure 进行相关的工程结构设置 。

    2)fatpenguin数据库中准备两张表 province表 和 city表。

    province表:

    CREATE TABLE `province` (
     `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

    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;

    注意事项:city表中的 provinceid字段作为 外键,代表的是省份表的主键的值

    2-代码编写

    package com.penguin1024.utils;
    import java.sql.*;
    // 定义连接数据库的JDBC工具类
    // 注意事项:工具类中的 可能产生异常的代码 不使用try..catch方式处理,一般使用抛出的方式。
    // 因为使用try...catch方式进行处理。代码一旦发生异常,工具类的调用者不好定位到发生异常的代码。
    public class JdbcUtil {
    
        // 静态代码块
        static {
            try {
                // 1-在JdbcUtil类加载时,加载mysql数据库的驱动
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        // 声明一个成员变量Connection对象 ,且需定义为静态成员  (该代码由下列方法中的代码思考之后,添加的)
        // 静态方法中只能访问静态成员,不能访问到实例成员。
        static Connection conn = null;
    
    
        // 2-定义:获取数据库连接Connection对象的方法
        // 注意:Connection 是java.sal.Connection(接口)。为什么? —— 面向接口编程,好处是不用在乎该连接是由谁实现的
        public static Connection getConnection() throws SQLException {
    
            String user = "jdbc:mysql://localhost:3306/fatpenguin";
            String url = "root";
            String password = "111";
    
            //重点注意:
            //思考什么时候需要创建Connection接口对象?每次使用时候都需要创建新的连接吗?
            //当conn = null时,才需要创建一个新的Connection接口对象。
    
    
            // Connection conn = null;错误。不能在此处将conn变量定义为局部变量。
            // 这样的写的话,下面的判断结果永远是false值。
            // 因此需要将在类中定义为静态成员: private static Connection conn = null;
    
            // conn值为null,或conn被关闭时,需要重新创建Connection对象。
    
            // 如果Connection对象为null,或者Connection对象已经被关闭掉的情况下
            if (conn == null || conn.isClosed()  ){
                // 满足以上条件,则创建新的Connection对象。
                conn = DriverManager.getConnection(user, url, password);
            }
            return conn;
        }
    
        // 3-定义:关闭相关资源
        public static void close(Connection conn, Statement stmt, ResultSet rs) throws SQLException {
            // 关闭资源1
            // 如果conn不等于null,且conn也没有被关闭的情况下。
            if (conn != null && !conn.isClosed()) {
                conn.close(); // 关闭
            }
    
            // 关闭资源2
            if (stmt != null && !conn.isClosed()) {
                stmt.close(); // 关闭
            }
    
            // 关闭资源3
            if (rs != null && !conn.isClosed()) {
                rs.close(); // 关闭
            }
        }
    }
    JdbcUtil.java
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>使用json格式的数据</title>
    
        <script type="text/javascript">
          // 使用浏览器内存中的异步对象,代替浏览器发起ajax请求,传递参数给服务器, 服务器返回数据。
    
          //1.创建异步对象 (异步对象使用js创建和管理的。)
          function search() {
            // 1-创建异步请求对象
            var xmlHttpRequest=  new XMLHttpRequest();
    
            // 2-绑定onreadystatechange事件
            xmlHttpRequest.onreadystatechange = function () {
    
              // 5-对从服务端中返回的数据做相关处理
    
              // 判断:若 异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态的情况下。
              if (xmlHttpRequest.readyState==4 && xmlHttpRequest.status ==200){
    
                // 获取服务器发送来的数据  (在此处,传递过来的是一个json格式的字符串)
                var data = xmlHttpRequest.responseText;
    
                //JavaScript中的eval(string)函数执行括号中的代码, 把json字符串转为json对象
                var jsonobj = eval("(" + data + ")");
    
                // 调用自定义的数据处理函数:来更新dom对象,更新页面数据
                  callback(jsonobj);
    
              }
    
            }
            // 3-初始异步请求对象 (初始化请求数据)
    
            //获取proid文本框的值 (用户在界面中输入的值)
            var proid = document.getElementById("proid").value;
    
            // 使用js中的函数encodeURI(String uri) 对字符串 进行编码  (可以解决JS中的中文参数乱码问题)
            proid = encodeURI(proid);
    
            xmlHttpRequest.open("get","${pageContext.request.contextPath}/queryProviceServlet?proid="+proid,true);
    
            // 4-向服务器发送请求
            xmlHttpRequest.send();
          }
    
          // 定义一个函数,来处理服务器端返回的数据
          function callback(json){
              document.getElementById("proname").value = json.name;
              document.getElementById("projiancheng").value=json.jiancheng;
              document.getElementById("proshenghui").value= json.shenghui;
          }
    
    
        </script>
    
      </head>
      <body>
      <p>ajax请求使用json格式的数据</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>
        <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>
    index.jsp
    package com.penguin1024.entity;
    
    // 定义Province实体类
    public class Province {
        private Integer id;
        private String name;
        private String jiancheng;
        private String shenghui;
    
        // 提供无参构造方法
        public Province() {
        }
    
        // 提供set/get 方法
    
        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;
        }
    }
    Province.java
    package com.penguin1024.dao;
    import com.penguin1024.entity.Province;
    import com.penguin1024.utils.JdbcUtil;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    // 对数据库中的数据执行相关的操作
    public class ProvinceDao {
        // 根据用户输入的省份id,查询出该id值所对应的省份信息(返回值是一个完整的实体类Province对象)
        public Province queryProvinceById(Integer provinceid){
    
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet res = null;
    
            // 声明一个Province类型的成员变量
            Province province = null;
    
    
            try {
                 // 1-借助编写好的JdbcUtil工具类,获取Connection 数据库连接对象
                 conn = JdbcUtil.getConnection();
    
                 // 2-编写SQL语句框架
                 String sql = "select id,name,jiancheng,shenghui from province where id = ?";
    
                 // 3-对SQL语句框架进行预编译处理 (避免SQL注入情况的产生)
                 ps = conn.prepareStatement(sql);
    
                 // 4-对SQL语句框架中的占位符,设置具体的参数值
                ps.setInt(1,provinceid);
    
                // 5-执行SQL语句,并接收返回的结果集
                 res = ps.executeQuery();
    
                 // 6-遍历处理查询结果集
    
    
                while (res.next()){
                    // 创建实体类Province
                    province = new Province();
    
                    // 为实体类的"id"属性 赋值
                    province.setId(res.getInt("id"));
                    // 为实体类的"name"属性 赋值
                    province.setName(res.getString("name"));
                    // 为实体类的"jiancheng"属性 赋值
                    province.setJiancheng(res.getString("jiancheng"));
                    // 为实体类的"shenghui"属性 赋值
                    province.setShenghui(res.getString("shenghui"));
                 }
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
    
                try {
                    // 7-借助编写好的JdbcUtil工具类,关闭相关资源
                    JdbcUtil.close(conn,ps,res);
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
    
    
            // 8-返回省份id编号所对应的省份信息(即一个完整的Province对象)
            return province;
        }
    
    }
    ProvinceDao.java
    package com.penguin1024.controller;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.penguin1024.dao.ProvinceDao;
    import com.penguin1024.entity.Province;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    // 执行相关的业务逻辑操作
    public class QueryProviceServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            // 定义一个字符串类类型的 默认值 {} :表示json格式的数据
            String jsonStr = "{}";
    
            // 1-对请求参数做相关处理
            // 覆盖此请求体中使用的字符编码的名称。 (解决post方式的中文乱码问题)
            request.setCharacterEncoding("utf-8");
            // 接收来自Ajax异步对象发送来的请求参数
            String proidStr = request.getParameter("proid");
            // 将字符串类型的省份id编号,转换为Integet类型
            Integer provinceId = Integer.valueOf(proidStr);
    
            // 2-访问Dao层对象,从数据库中查询数据
    
            // 用户在查询界面中输入的不是空字符串
            // 且输入的id编号在转换为Integer类型之后的值不为null
            if(  proidStr.trim().length() >0 && provinceId != null ) {
                // 创建dao对象
                ProvinceDao dao = new ProvinceDao();
    
                //  调用dao对象的方法 — —根据用户添加的省份id编号,到数据库中查找出该编号对应的省份对象
                Province province = dao.queryProvinceById(provinceId);
    
                //需要使用jackson工具类 把 Provice对象转为json格式的字符串
                ObjectMapper om  = new ObjectMapper();
                jsonStr =  om.writeValueAsString(province);
    
            }
    
            // 3-向发送请求的Ajax异步请求对象返回查询到的结果
    
    
            //把获取的数据,通过网络传给ajax中的异步对象,响应结果数据
            //指定服务器端(servlet)返回给浏览器的是json格式的数据,并通知浏览器使用使用utf-8编码(解决响应的中文乱码问题)
    
            response.setContentType("application/json;charset=utf-8");
    
            // 获取标准输出流
            PrintWriter out = response.getWriter();
    
            // 往标准输出流中写入的数据,会被响应到发出相应请求的Ajax异步对象的responseText属性中。
            out.println(jsonStr);
    
            // 清空缓存
            out.flush();
    
            // 关闭流
            out.close();
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }
    QueryProviceServlet.java

    3-结果查询

     输入编号,点击搜索,显示出对应的结果:


    相关资料:

         《王鹤讲AJAX》

  • 相关阅读:
    Android之Wifi使用
    Android之浮动小窗口
    Android之Socket的基于UDP传输
    Android之基本常见知识(持续更新)
    Android之打开闪光灯关键代码
    Android之Oauth验证(一)
    Android之WebView简易应用
    Android之短信广播接收内容
    Google HTML/CSS 代码风格指南
    几个 HTML 标签的用法
  • 原文地址:https://www.cnblogs.com/penguin1024/p/15501711.html
Copyright © 2011-2022 走看看