Servlet處理原生Ajax請求


萌新小白人生中的第一篇博客,難免會有差錯,還望各位大佬多多包涵。

1. Ajax技術簡介 

    Ajax(Asynchronous JavaScript and XML,異步JavaScript和XML)時一種創建交互式網頁應用的網頁開發技術,它並不是一項新的技術,其產生的目的是用於實現頁面的局部刷新。通過Ajax技術可以使之前的應用程序在每次提交時不用進行頁面的整體刷新,從而提升操作的性能。

2. Servlet概念

    Servlet(服務器端小程序)是使用java編寫的服務器端小程序,可以像JSP一樣,生成動態的Web頁。不過,Servlet側重於邏輯控制,JSP側重於視圖展示。Servlet主要運行在服務器端,並由服務器調用執行,是一種按照Servlet標准開發的類。Servlet最大的好處就是可以處理客戶傳來的HTTP請求,並返回一個響應。

3. 同步和異步

    同步:客戶端發送請求給服務端,在等待服務端響應請求的這段時間,客戶端不能做其他事情,只能等待。服務器端做完了才返回給客戶端,這時客戶端就可以做其他事情了。用戶使用起來可能不太友好,但是有時我們必須拿到服務端的數據才能進行下一步操作。比如我給你打電話,你必須接通電話我才可以和你通話。

    異步:客戶端發送請求給服務端,在等待服務端響應請求的這段時間,客戶端可以做其他事情,不用等待。節約了時間。提高了效率。比如發短信。一條短信發完后,不管你看沒看,回復沒回復,我可以再發下一條短信。不過,也有可能造成短信干擾。所以要慎重。當然,打電話和發短信的前提是必須有手機,手機必須有話費。(說一句廢話)。

4. Servlet處理原生Ajax請求(不發送數據/發送key/value數據/發送json格式數據)

開發環境:eclipse+tomcat+jsp+javascript+ajax+servlet

 

4.1 Servlet處理原生Ajax請求(不攜帶數據,返回普通文本)

    (1) 搭建環境:

    在eclipse中新建Java web項目(會自動導入JRE System Library包),比如我把項目名字寫為AjaxDemo,並將項目部署到tomcat服務器上,下面是eclipse中項目的目錄結構:

    

我們先不管lib中的jar包,下面我會進行分析,一步一步來。下面我們進行開發。

   (2)編寫inedex.jsp頁面

     在WebContent根目錄下新建index.jsp文件,文件內容如下:

      

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 
 3 <%-- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> --%>  4 <%
 5     String path = request.getContextPath();  6     String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()  7             + path + "/";  8 %>
 9 <!DOCTYPE html>
10 <html>
11 <head>
12 <base href="<%=basePath%>">
13 <title>I LOVE YOU</title>
14 <link rel="stylesheet" type="text/css" href="">
15 <script type="text/javascript" src="index.js"></script>
16 
17 </head>
18 <body>
19 
20 <button id="mybutton" value="異步請求服務器" onclick="fun1()" >發送數據格式為key/value的原生ajax請求</button>
21 <spand id="show" />
22 
23 <br/>
24 
25 <hr/>
26 
27 <button id="mybutton1" value="異步請求服務器" onclick="fun2()" >發送數據格式為json的原生ajax請求</button>
28 <spand id="show1" />
29 
30 
31 <br/>
32 <hr/>
33 
34 <button id="mybutton2" value="異步請求服務器" onclick="fun3()" >不發送數據</button>
35 <spand id="show2" />
36 
37 </body>

 

這個頁面我們編寫了三個按鈕,並且都注冊了事件,可以調用js文件中對應的函數來響應按鈕。這里我們看id="mybutton2"這個按鈕(第三個),不發送數據這個按鈕。<span>標簽的作用主要是為了顯示返回的內容。我們注意到這個jsp文件引用了javascript文件。下面我們編寫js文件。

(3)編寫inedex.js文件

   

 1 /**  2  *  3  */
 4 //原生ajax提交key/value數據
 5 function fun1(){  6     
 7     var value="username=wly&password=1314520"; //key/value類型  8     var x=new XMLHttpRequest();   //創建ajax對象
 9     x.onreadystatechange=function(){     //對ajax對象進行監聽 
10         if(x.readyState==4){         //4表示解析完畢 
11             if(x.status==200){            //200為正常返回
12                 var data=x.responseText;   //返回的文本內容
13                 document.getElementById("show").innerHTML=data; 14                 console.log(data);  //web控制台打印
15  } 16  } 17  } 18     
19     //(1)發送方式
20     //(2)發送地址
21     //(3)是否異步,true為異步,false為同步 
22     x.open("POST","AjaxServlet",true); 23     x.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 24     x.send(value);  //發送 
25 } 26 
27 
28 //原生ajax提交json數據
29 function fun2(){ 30     var user={ 31         "username":"wly", 32         "password":"1314521"
33  }; 34     var x=new XMLHttpRequest();   //創建ajax對象
35     x.onreadystatechange=function(){     //對ajax對象進行監聽 
36         if(x.readyState==4){         //4表示解析完畢 
37             if(x.status==200){            //200為正常返回
38                 var data=JSON.parse(x.responseText);   //把json字符串解析為javascript對象
39                 document.getElementById("show1").innerHTML=data.message+" "+data.user.username+" "+data.user.password; 40  console.log(data); 41  console.log(data.meaasage); 42  console.log(data.user); 43  } 44  } 45  } 46     
47     //(1)發送方式
48     //(2)發送地址
49     //(3)是否異步,true為異步,false為同步 
50     x.open("POST","AjaxServlet1",true); 51     x.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 52     
53     //把javascript對象轉化為json字符串
54  x.send(JSON.stringify(user)); 55 } 56 
57 
58 //原生ajax請求(不發送數據)
59 function fun3(){ 60     
61     
62     var x=new XMLHttpRequest();   //創建ajax對象
63     x.onreadystatechange=function(){     //對ajax對象進行監聽 
64         if(x.readyState==4){         //4表示解析完畢 
65             if(x.status==200){            //200為正常返回
66                 var data=x.responseText;   //返回的文本內容
67                 document.getElementById("show2").innerHTML=data;//將內容顯示在span標簽中
68                 console.log(data);  //web控制台打印
69  } 70  } 71  } 72     
73     //(1)發送方式
74     //(2)發送地址
75     //(3)是否異步,true為異步,false為同步 
76     x.open("POST","AjaxServlet2",true); 77     //設置請求頭信息
78     x.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 79     x.send(null);  //發送 ,不發送數據,使用null
80 }

 

我們來看fun3()這個函數,這里我們使用原生ajax提交請求,這里我們不發送數據,所以send中的參數為null。代碼里面都有注釋,這里不做過多解釋。

既然提交了請求,那么我們必須編寫服務器端代碼來處理ajax請求。接下來servlet就登場了。

(4)編寫Servlet文件

   

 1 package com.servlet;  2 
 3 import java.io.IOException;  4 
 5 import javax.servlet.ServletException;  6 import javax.servlet.http.HttpServlet;  7 import javax.servlet.http.HttpServletRequest;  8 import javax.servlet.http.HttpServletResponse;  9 
10 public class AjaxServlet2 extends HttpServlet { 11 
12     protected void doGet(HttpServletRequest request, HttpServletResponse response) 13             throws ServletException, IOException { 14 
15         // 設置發送到客戶端的響應的內容類型為html,編碼方式為UTF-8
16         response.setContentType("text/html;charset=UTF-8"); 17         // 返回內容
18         response.getWriter().write("我想你了!");// 返回一個普通字符串
19  } 20 
21     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 22         this.doGet(req, resp); 23  } 24 }

此時servlet處理Ajax請求非常簡單,因為不需要接受數據,所以只返回普通文本就行了。注意response.getWriter()返回的是PrintWriter,這是一個打印輸出流。調用其write方法輸出文本內容。接下來我們再web.xml配置servlet。

 

(5)web.xml配置Servlet

   為什么要在web.xml中配置Servlet呢?因為當我們在瀏覽器輸入url地址時,發送請求給tomcat容器,tomcat必須要加載相對應servlet,並調用Servlet去處理請求,所以必須要在web.xml中配置servlet。如果不配置的話,就會找不到相應的Servlet來處理。

   

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
 3   <display-name>AjaxDemo</display-name>
 4   <welcome-file-list>
 5     <welcome-file>index.html</welcome-file>
 6     <welcome-file>index.htm</welcome-file>
 7     <welcome-file>index.jsp</welcome-file>
 8     <welcome-file>default.html</welcome-file>
 9     <welcome-file>default.htm</welcome-file>
10     <welcome-file>default.jsp</welcome-file>
11   </welcome-file-list>
12   
13   
14   <servlet>
15       <servlet-name>AjaxServlet</servlet-name>
16       
17       <servlet-class>com.servlet.AjaxServlet</servlet-class>
18   </servlet>
19   
20   <servlet>
21       <servlet-name>AjaxServlet1</servlet-name>
22       
23       <servlet-class>com.servlet.AjaxServlet1</servlet-class>
24   </servlet>
25   
26    
27    <servlet>
28       <servlet-name>AjaxServlet2</servlet-name>
29       
30       <servlet-class>com.servlet.AjaxServlet2</servlet-class>
31   </servlet>
32   
33   
34   
35   
36   
37   
38   <servlet-mapping>
39       
40       <servlet-name>AjaxServlet</servlet-name>
41       <url-pattern>/AjaxServlet</url-pattern>
42       
43   </servlet-mapping>
44   
45   
46   <servlet-mapping>
47       
48       <servlet-name>AjaxServlet1</servlet-name>
49       <url-pattern>/AjaxServlet1</url-pattern>
50       
51   </servlet-mapping>
52   
53   
54   <servlet-mapping>
55       
56       <servlet-name>AjaxServlet2</servlet-name>
57       <url-pattern>/AjaxServlet2</url-pattern>
58       
59   </servlet-mapping>
60     
61 </web-app>

 

我們看到AjaxServlet2配置好了。說明一下。配置servlet有2個標簽。第一個是<servlet></servlet>這里面我們配置的是servlet名稱和全類路徑。第二個

<servlet-mapping></servlet-mapping>配置的是servlet名稱(和第一個標簽的servlet名稱保持一致)和映射路徑。這里我使用斜杠/加上自己的路徑。

我們注意到<welcome-file-list>標簽配置有一個index.jsp文件,相當於是一個歡迎頁面。到時我們寫url請求地址時就不用寫文件名字了。(方便)

下來我們跑一下程序。

 

(5)運行程序

   啟動tomcat,在谷歌瀏覽器地址欄上輸入請求地址url:localhost/AjaxDemo/ 

   好了,ok。點擊按鈕(不發送數據)運行就行了。效果展示圖:

   

注意:一般請求地址為localhost:端口號/項目名/jsp文件名。localhost意為本地主機,就是這台計算機。tomcat的默認端口號為8080,我把tomcat的端口號改為了80,而80端口號是HTTP協議的默認端口號。所以我可以省略掉80端口號。其實在你輸入網站的時候其實瀏覽器(非IE)已經幫你輸入協議了。后面的jsp文件名我也省了,因為得益於上面標簽<welcme-file-list>的配置。哈哈。方便了好多。同理。我們可以實現其他實例。

 

4.2 Servlet處理原生Ajax請求(發送key/value數據,返回普通文本)

(1)編寫jsp文件

   上面有index.jsp代碼,看第一個按鈕就行了。同理。

(2)編寫js文件

   上面有index文件,看第一個函數fun1()就行了。注釋都有。注意key/value的格式為data="username=wly&password=1314520"。多個鍵值對可以用&來連接,然后再使用send(data)方法進行發送數據。

 (3)編寫Servlet文件

   

 1 package com.servlet;  2 
 3 import java.io.IOException;  4 
 5 import javax.servlet.ServletException;  6 import javax.servlet.http.HttpServlet;  7 import javax.servlet.http.HttpServletRequest;  8 import javax.servlet.http.HttpServletResponse;  9 
10 public class AjaxServlet extends HttpServlet { 11 
12     protected void doGet(HttpServletRequest request, HttpServletResponse response) 13             throws ServletException, IOException { 14 
15         response.setContentType("text/html;charset=UTF-8"); 16         String username = request.getParameter("username"); //獲取username的內容 17         String password = request.getParameter("password"); //獲取password的內容 18         System.out.println(username + " " + password); 19         response.getWriter().write("haha " + "username: " + username + " password: " + password); //連接一個普通字符串返回 20 
21  } 22 
23     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 24         this.doGet(req, resp); 25  } 26 }

此時servlet要做的事情,接受前台傳來的數據和返回內容。獲取前台傳來的內容,使用request.getParameter(String paramString)方法。可以根據參數的名稱獲取相應的內容。這個方法非常重要。獲取到了以后,我們只返回一個普通文本字符串即可。

(4)web.xml配置servlet

   同理。上面web.xml已經配置好了。配置的是AjaxServlet。這里不做過多解釋。

(5)運行程序

   啟動tomcat,在谷歌瀏覽器地址欄上輸入請求地址url:localhost/AjaxDemo/ 

   好了,ok。點擊第一個按鈕運行就行了。效果展示圖:

   

 

4.3 Servlet處理原生Ajax請求(發送json數據,返回json數據)

(1)Json

      JSON(JavaScript Object Notation, JS 對象簡譜) 是一種輕量級的數據交換格式。對於Ajax應用程序來說,json比xml更快更易使用。人類易於閱讀和書寫。機器很容易解析和生成。它基於JavaScript編程語言(標准ECMA-262第三版-1999年12月)的子集。JSON是一種文本格式,它完全獨立於語言。這些屬性使JSON成為理想的數據交換語言。項目中常用的Json類庫:Gson(谷歌公司研發),FastJson(阿里巴巴研發),Jackson(簡單易用,依賴包少),Json-lib(使用廣泛,依賴包較多)。

(2)導入jar包

      因為涉及到json數據格式的處理,所以我們必須導入json相關的包以及依賴包進行處理。我們使用應用比較廣泛的Json-lib類庫。上面項目結構里面有7個jar包(lib下面)。可以發現上面json-lib庫的核心jar包是json-lib-2.4-jdk15.jar,其他幾個都是依賴包。Json-lib是一個Java類庫,用於將bean,集合,java數組和XML轉換為JSON,然后再次轉換為bean和DynaBeans(動態bean)。

(3)新建實體類(User)

   因為涉及到將json對象轉化為java對象,將java對象轉化為json對象。所以要建立User對象,有2個屬性,username和password。並提供setter和getter方法,還有toString()方法。

   

package com.entity; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [username=" + username + ", password=" + password + "]"; } }

 

(4)編寫jsp文件

   同理。看第二個按鈕即可。

(5)編寫js文件

   同理。上面index.js文件中的fun2()函數。這里做一下解釋。注意json的數據格式var user={"username":"wly", "password":1314521}。這里我們把數據value值直接寫了。(為了方便)。實際開發中我們應該獲取頁面的username的value值。password的value值。可以使用 document.getElementById("id").value來獲取頁面數據。還要注意有2個方法。觀察fun2()。我們發現發送的時候,做了一下處理,使用的是JSON.stringify(user)。這個函數的作用主要是將javascript對象轉化為json字符串,因為定義的user是一個var類型,它是一個javascript對象,只是內容定義的是符合json數解析為javascript對象據規范的格式。所以才可以轉化。轉化為json字符串才可以發送。在把參數傳入send()方法里面進行發送。同理。還有一個方法JSON.parse(返回的json字符串),它的作用是將返回的json字符解析為javascript對象,然后再進行前台頁面數據的顯示。

(6)編寫servlet文件

   第一步,先編寫一個json的工具類,用來接受前台傳來的json字符串,並把json字符串轉化為json對象。

   

 1 package com.util;  2 
 3 import java.io.BufferedReader;  4 import java.io.IOException;  5 import java.io.InputStreamReader;  6 import java.io.UnsupportedEncodingException;  7 
 8 import javax.servlet.http.HttpServletRequest;  9 
10 import net.sf.json.JSONObject; 11 
12 public class JsonReader { 13 
14     public static JSONObject receivePost(HttpServletRequest request) throws UnsupportedEncodingException, IOException { 15 
16         // 讀取請求內容
17         BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8")); 18 
19         String line = null; 20         StringBuilder sb = new StringBuilder(); 21 
22         while ((line = br.readLine()) != null) { 23  sb.append(line); 24  } 25 
26         // 將json字符串轉化為json對象
27         JSONObject json = JSONObject.fromObject(sb.toString()); 28         return json; 29  } 30 
31 }

第二步,編寫servlet類。

 

 1 package com.servlet;  2 
 3 import java.io.IOException;  4 
 5 import javax.servlet.ServletException;  6 import javax.servlet.http.HttpServlet;  7 import javax.servlet.http.HttpServletRequest;  8 import javax.servlet.http.HttpServletResponse;  9 
10 import com.entity.User; 11 import com.util.JsonReader; 12 
13 import net.sf.json.JSONObject; 14 
15 public class AjaxServlet1 extends HttpServlet { 16 
17     protected void doGet(HttpServletRequest request, HttpServletResponse response) 18             throws ServletException, IOException { 19 
20         // response.setContentType("text/html;charset=UTF-8");
21 
22         response.setContentType("application/json;charset=UTF-8"); //設置響應的內容類型和編碼 23         JSONObject json = JsonReader.receivePost(request); 24  System.out.println(json); 25 
26         // 將json對象轉化為java對象
27         User user = (User) JSONObject.toBean(json, User.class); 28 
29         JSONObject result = new JSONObject(); 30 
31         // 將user對象轉化為json對象,保存user
32         result.put("user", JSONObject.fromObject(user)); 33         result.put("message", "返回成功"); 34  response.getWriter().print(result); 35  } 36 
37     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 38         this.doGet(req, resp); 39  } 40 }

 

BufferedReader可以用來讀取文件或者接收來自鍵盤(控制台)的信息。它比Scanner更加快捷,能夠大幅度縮短程序運行時間。它下面的readline()方法可以一次性讀取一行文字(String),非常方便。需要注意的是,使用BufferedReader對象的readLine()方法必須處理java.io.IOException異常(Exception)。以及,在使用完BufferredReader以后,需要用close()方法關閉流。上面我們用BufferedReader對象來接受請求內容。並使用StringBuilder對象進行存儲StringBuilder是一個字符串變量,單線程下效率比較高。JSONObject類是json-lib核心庫中的一個比較重要的類,這里我們使用其中的2個方法就行。其他的自己看源碼。

一個是public static JSONObject fromObject(Object object),這是JSONObject類的一個靜態方法,將Object類型數據(或者是java對象)轉化為JSONObject對象返回。另一個是public static Object toBean(JSONObject jsonObject, Class beanClass)方法,它的作用主要用於將json對象轉化為Object類型(或者說java對象)。注意上面PrintWritter的print()方法,其實底層還是調用了write方法。其實最終返回的還是json字符串。自己感興趣的話可以自己研究一下源碼。

(7)web.xml配置servlet

  同理。上面已經配置。配置的是AjaxServlet1。

(8)運行程序

   同理。輸入url地址。點擊第二個按鈕就行了。效果圖如下:

   

 

5. 總結

   (1)注意jsp文件引入js文件的路徑問題,這里我們可以把2個文件都放在WebContent根目錄下。

   (2)注意ajax提交的地址找不到時,要檢查web.xml是否配置正確,也可以使用${pageContext.request.contextPath}/配置的映射地址。相當於是全路徑。

   (3)Ajax傳給后台json數據時,需要使用JSON.stringify(data)將javascript對象轉化為json字符串。與之相對應的方法是JSON.parse(data)。

   (4)Ajax使用JSONObject類處理json數據時,注意json-lib的jar包以及依賴包一定要導全。

   (5)json-lib類庫性能分析:json-lib最開始的也是應用最廣泛的json解析工具,json-lib 不好的地方確實是依賴於很多第三方包,對於復雜類型的轉換,json-lib對於json轉換成bean還有缺陷, 比如一個類里面會出現另一個類的list或者map集合,json-lib從json到bean的轉換就會出現問題。json-lib在功能和性能上面都不能滿足現在互聯網化的需求。

    本篇博客源碼鏈接:https://pan.baidu.com/s/1fTR0mpfmj9-D7tPrONOu8g         提取碼:swsa 

 


免責聲明!

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



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