1. 程式人生 > >Struts2處理(jQuery)Ajax請求

Struts2處理(jQuery)Ajax請求

1. Ajax

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

2. jQuery

    jQuery是一個JavaScript函式庫,極大的簡化了JavaScript程式設計,很容易學習。jQuery是目前最流行的開源js框架,並且提供了大量的擴充套件。

3. Struts2框架

    瞭解一下MVC模式,MVC 模式代表 Model-View-Controller(模型-檢視-控制器) 模式。MVC是一種軟體設計典範。這種模式用於應用程式的分層開發。

    Model(模型) - 模型代表一個存取資料的物件或 JAVA POJO。它也可以帶有邏輯,在資料變化時更新控制器。

    View(檢視) - 檢視代表模型包含的資料的視覺化。

    Controller(控制器) - 控制器作用於模型和檢視上。它控制資料流向模型物件,並在資料變化時更新檢視。它使檢視與模型分離開。

    Apache Struts是一個免費的開源MVC框架,用於建立優雅的現代Java Web應用程式。它支援約定勝於配置(約定大於配置,簡單來說就是簡化我們的開發的,使程式碼更加簡潔,並且有很好的可重用性和可擴充套件性),可以使用外掛體系結構進行擴充套件,並且附帶了支援REST,AJAX和JSON的外掛。Struts2是一個基於MVC設計模式的Web應用框架,它本質上相當於一個servlet,在MVC設計模式中,Struts2作為控制器(Controller)來建立模型與檢視的資料互動。Struts2是在Struts1和WebWork的技術基礎上進行全新開發,以WebWork為核心,採用攔截器的機制來處理使用者的請求,這樣的設計也使得業務邏輯控制器能夠與ServletAPI完全脫離開(解耦合),方便了我們進行Java Web開發。

4. Struts2處理(jQuery)Ajax請求((傳送key/value資料)/傳送json資料)

     開發環境:eclipse+Struts2+jsp+jQuery+Ajax+Jackson+tomcat

4.1 Struts2處理(jQuery)Ajax請求(不傳送資料,返回普通文字)

(1) 搭建環境

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

    

專案結構很簡單。這裡我們看一下lib目錄下的jar包,因為我們使用了Struts2框架進行開發,所以必須匯入Struts2開發包。Struts2有很多開發包,這裡我們匯入我們想用的就行了。如上所示。Struts2開發包:asm三個jar包,commons三個,freemarker的jar包,ongl的jar包,strts2-core和核心jar包,Struts2內建的json外掛jar包struts2-json(不可以忘記匯入哈!),用來處理json資料。javassist的jar包。還有一個xwork-core核心包。日誌jar包:log4j(2個)。Jackson開發包:3個。(不懂的話可以看我上篇部落格)。好了,jar包就說完了。下面進行開發。

(2)編寫jsp檔案

   客戶端不傳送資料,伺服器端返回一個普通文字。這裡我們主要熟悉一下流程,看一下效果,雖然說不傳送資料沒多大意義。

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%-- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> --%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<title>I LOVE YOU</title>
<link rel="stylesheet" type="text/css" href="">
<script type="text/javascript" src="myindex.js"></script>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>


</head>
<body>

<button id="mybutton1" value="struts2處理(jQuery)Ajax請求" onclick="fun1()" >(jquery)ajax請求(不傳送資料)</button>
<spand id="show1" />

<br/>
<hr/>



</body>

index.jsp很簡單,就定義了一個按鈕。呼叫對應函式。函式名要和js中所寫的對應一致。注意要引入自己編寫的js檔案和jQuery的js檔案(注意路徑)。

 

(3)編寫myindex.js檔案

 

/**
 * 
 */
//(jQuery)Ajax請求不傳送資料
function fun1(){
    
    $.ajax({
        
        type:"POST",
        url:"UserAction1",
        data:"",
        success:function(data){
            
            $("#show1").html(data);
            
        }            
    });
        
}

 

定義了fun1()函式,注意jQuery的元素選擇器的id和html定義<span>標籤的id保持一致,主要是為了顯示內容。麼啥好說的,就是傳送的使key/value資料。

 

(4)新建User實體類

//
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 + "]";
    }

}

很簡單,有2個屬性(username和password)。注意Ajax傳遞的引數名稱要和User類的屬性保持一致(面向物件。java物件對屬性的封裝)。

(5)編寫Action類

   Action類用來處理請求,響應客戶端。

 

package com.action;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

//不接受引數,列印簡單文字
public class UserAction1 extends ActionSupport {

    // 獲取response物件
    private HttpServletResponse response = ServletActionContext.getResponse();

    // 只是列印一個字串文字內容(也可以給客戶端返回json資料,處理一下就行了。這裡返回文字,主要看一下不同的效果)
    public String myexcute1() {

        response.setContentType("text/html;charset=utf-8");
        String str = "我想你了!哈哈哈!";
        try {
            response.getWriter().print(str);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

 

程式碼很簡單,都有註釋。新建一個Action類,繼承了ActionSupport。可以通過ServletActionContext.getResponse()方法獲取到response物件。ServletActionContext(com.opensymphony.webwork.ServletActionContext),該類直接繼承了ActionContext提供直接與Servlet相關物件訪問的功能
ServletActionContext執行緒安全。這個類主要用於獲取servlet的相關物件。使用response獲取列印輸出流,輸出一個普通文字。說一下ActionSupport類, struts2不要求我們自己設計的action類繼承任何的struts基類或struts介面,但是我們為了方便實現我們自己的action,大多數情況下都會繼承ActionSupport類,並重寫此類裡的public String execute() throws Exception方法。因為此類中實現了很多的實用藉口,提供了很多預設方法,這些預設方法包括國際化資訊的方法、預設的處理使用者請求的方法等,這樣可以大大的簡化Acion的開發。Struts獲取請求,怎麼知道呼叫那個Action的方法進行處理呢。下面我們配置Struts2的主配置檔案struts.xml。

(6)配置struts.xml檔案

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <constant name="struts.devMode" value="true"></constant>    
   <constant name="struts.i18n.encoding" value="UTF-8"></constant>
   
    <package name="default" namespace="/" extends="struts-default,json-default">

        <action name="UserAction1" class="com.action.UserAction1" method="myexcute1">
            <result >
                
            </result>
        </action>  
                  
    </package>
    
</struts>

 

子標籤constant:定義一些常量。struts.devMode啟動開發者模式。struts.i18n.encoding設定請求的編碼。這些常量的定義位於struts2核心開發包的default.proprties資原始檔中。子標籤pakage:name="default"包名,可以隨便取,但是不能重複。一個<pakage>可以配置多個<action>。namespace:名稱空間。Struts2請求的訪問路徑:http://ip地址:埠號/工程名/名稱空間/Action的名稱。extends代表繼承的包,Struts2的預設包“default”是繼承於"Struts-dafault"包的,struts-default包是在struts-default.xml中定義,struts-default.xml也是Struts2預設配置檔案,所以Struts2每次都會自動載入 struts-default.xml檔案。struts-defalut.xml位於struts2-core核心包下面。注意到還繼承了一個json-default包,json-default是繼承struts-default,json這個result type(返回型別)是在json-default (struts2-json-plugin-2.1.8.1.jar\struts-plugin.xml)裡面定義的。<action>標籤。用來呼叫某個Action類對應的方法進行處理客戶端請求的。我們先來看配置的第一個<action>。name設定action的請求路徑。比如我們設定為name="UserAction1",注意Ajax提交請求的url必須和此時設定的action的name保持一致,不然找不到。class就是Action類的全路徑。method就是Action類中的方法名稱。上面我們的方法名為myexcute1,所以設定為method="myexcute1",不要帶括號以及引數,只書寫方法名稱就行了。<result>表示返回的結果集,有2個屬性,一個是name:對應Action返回邏輯檢視名稱,預設為success。一個是type:返回結果型別,預設為dispatcher。因為我們這個方法只返回普通字串,所以<result>裡面就不用寫了。空空如也。

(7)配置web.xml檔案

   web.xml檔案還是很重要的,它是tomcat的配置檔案,當我們啟動一個web專案容器的時候,它首先會載入web.xml檔案。

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>StrutsProject</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  
  <!--配置struts2的核心過濾器  -->
  
       <filter>
           <!-- 核心過濾器名稱 -->
         <filter-name>struts2</filter-name>
         <!-- 費核心過濾器全類路徑(包.類) -->
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
     
     <filter-mapping>
         <filter-name>struts2</filter-name>
         <!-- 攔截路徑 -->
         <url-pattern>/*</url-pattern>
     </filter-mapping>
 
</web-app>

 

配置很簡單,就配置了一個Struts2的核心過濾器StrutsPrapareAndExcuteFilter。FilterDispatcher是早期struts2的過濾器,後期的都用StrutsPrepareAndExecuteFilter了。StrutsPrepareAndExecuteFilter名字可知,prepare與execute,前者表示準備,可以說是指filter中的init方法,即配製的匯入;後者表示進行過濾,指doFilter方法,即將request請求,轉發給對應的 action去處理。在使用struts的時候要在web.xml中配置一個過濾器,來攔截使用者發起的請求,並進行一些預處理,根據配置檔案把請求分配給對應的action並將請求中的引數與action中的欄位進行對應賦值。

(8)執行程式

   啟動tomcat,在瀏覽器位址列輸入url,點選按鈕,檢視效果。完美執行。

 

4.2 Struts2處理(jQuery)Ajax請求(傳送key/value資料,返回json資料)

(1)匯入Jackson包

   上面導包已經導好了,這裡不多說。jackson所需3個jar包(注意要導全)。

(2)編寫jsp檔案

   同理,寫一個按鈕和顯示內容的span標籤。

<button id="mybutton2" value="struts2處理(jQuery)Ajax請求" onclick="fun2()" >傳送資料格式為key/value的(jquery)ajax請求</button>
<spand id="show2" /><br/>

 

(3)編寫js檔案

   

//使用jquery提交key/value資料(ajax請求)
function fun2(){
    
    $.ajax({
        
        type:"POST",
        url:"UserAction2",
        data:"username=wly&password=1314520",
        success:function(data){
            var value=JSON.parse(data);  //json字串轉化為js物件
            $("#show2").html(value.username+" "+value.password);
            
        }            
    });
        
}

 

提交路徑要和strutst.xml的action的name保持一致。返回的json字串要通過JSON.parse(data)方法解析為js物件(準確來說,是js可以操作的json物件)。

 

(4)編寫User實體類

   和上面User類一樣,有2個屬性username和password,提供setter,getter和toSring()方法。

 

(5)編寫Action類

   

package com.action;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.pojo.User;

//接受key/value引數,輸出json資料
public class UserAction2 extends ActionSupport implements ModelDriven<User> {

    // 注意一定要new一個實體物件
    private User user = new User();

    // 獲取response物件
    private HttpServletResponse response = ServletActionContext.getResponse();

    // 返回的結果集,必須提供getter和setter方法
    String result = null;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    // 返回json資料(利用jackson完成java物件與json的轉化)
    public String myexcute2() {

        response.setContentType("application/json;charset=UTF-8");
        System.out.println(user);
        ObjectMapper json = new ObjectMapper(); // 新建json物件

        try {
            result = json.writeValueAsString(user); // user物件轉化為json字串
            System.out.println(result);
        } catch (JsonGenerationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return SUCCESS; // 返回SUCCESS標誌,主配置檔案根據result標籤的name來跳轉頁面或者輸出內容。
                        // Struts2的常量(SUCCESS、NONE、ERROR、INPUT、LOGIN)
    }

    // 實現模型驅動ModelDriven介面的抽象方法
    @Override
    public User getModel() {
        // TODO Auto-generated method stub
        return user;
    }
}

 

這裡所以說一下。Struts2接受前臺傳來的資料的方法(2種)。第一種:屬性驅動。(1)使用變數的方式,把欄位寫在Action類中,並提供setter和getter方法。(2)使用物件的方式。把user物件當作屬性封裝到Action中,並提供setter和gettter方法。但是要注意前臺傳值。要使用變數.屬性的方式才可以獲得到。第二種:模型驅動。也就是本文所使用到的辦法。Action類通過實現com.opensymphony.xwork2.ModelDriven<T>介面,並實現介面中的抽象方法 public abstract T getModel(),不需要提供getter和setter方法。但是聲名物件的時候一定要例項化。前臺傳遞的引數名稱和實體類中的屬性名稱保持一致即可。這裡我們看上面public String myexcute2()個方法,這個方法其實就是獲取到user物件,然後利用jackson將user物件轉化為json字串輸出。最後返回一個SUCCESS常量,struts2會根據struts.xml配置檔案中的<result>的name和type進行頁面的跳轉或者輸出內容。注意這裡向客戶端輸出一個json字串的結果集,我們用result變數儲存起來,並且一定要提供result的setter和getter方法。方法很簡單。

 

(6)配置struts.xml檔案

   

<action name="UserAction2" class="com.action.UserAction2" method="myexcute2">         
            <!-- 返回json型別資料 -->
                    
            <result name="success" type="json">               
                <param name="root">result</param>
            </result>
 </action> 

 

配置很簡單,把這個<action>放入上面那個<package>標籤中就可以了(也可以重新寫一個<package>),這裡為了方便。注意result的name為success,剛才我們返回的是SUCCESS(代表action執行成功),這是一個struts2的常量,它的值為public static final String SUCCESS = "success"。struts2其他幾個常量

NONE(action執行成功,不跳轉頁面)、ERROR(action執行失敗)、INPUT(action為了執行成功需要多次輸入)、LOGIN(action不能執行,因為使用者沒有登入)。<result>標籤的type="json",表示返回的是json資料格式。這裡加上了一個param引數。<param name="root">result</param>中,result就是剛才我們action返回的結果集(有getter和setter方法)。name="root"表示從result結果集的根部進行遍歷。所以就可以正常返回並解析了。

 

(7)配置web.xml檔案

   web.xml的配置和上面一樣,就配置一個struts2核心過濾器就ok了。

(8)執行程式

   啟動tomcat容器,輸入地址,完美執行。

    

 

4.3 Struts2處理(jQuery)Ajax請求(傳送json資料,返回json資料)

(1)編寫jsp檔案

   匯入jar包就不說了,就是上面的。

<button id="mybutton3" value="struts2處理(jQuery)Ajax請求" onclick="fun3()" >傳送資料格式為json的(jquery)ajax請求</button>
<spand id="show3" /><br/>

   定義了一個按鈕和span標籤,很簡單。

(2)編寫js檔案

 

//使用jquery提交json資料(ajax請求)


function fun3(){
    
    var user={
            "username":"wly",
            "password":"1314520"    
    };    
$.ajax({
        
        type:"POST",
        url:"UserAction3",
        contentType:"application/json;charset=UTF-8",
        data:JSON.stringify(user),    //將js物件轉化為json字串
        dataType:"json",
        success:function(data){
            console.log(data);
            var value=JSON.parse(data);   //將json字串解析為js物件
            $("#show3").html(value.username+" "+value.password);            
        }            
    });
}

 

   上面沒啥好說的,就是一些熟悉的內容,不懂的話可以看我前2篇部落格。console.log(data)是在web瀏覽器的控制檯進行列印(谷歌瀏覽器找開發者工具)。

 

(3)新建User類

   不多說,和上面一樣。其實我們就只寫了一個User類。

(4)新建Action類

   第一步:編寫json工具類

   

package com.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pojo.User;

public class JsonUtil {

    public static User accept(HttpServletRequest request) throws UnsupportedEncodingException, IOException {

        // 讀取請求內容
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));

        String line = null;
        StringBuilder sb = new StringBuilder();

        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

        // 將json字串轉化為java物件
        ObjectMapper json = new ObjectMapper();
        User user = json.readValue(sb.toString(), User.class);
        return user;
    }

}

 

   這個類沒啥好說的,就是通過BufferedReader類來讀取請求內容,並把請求內容按行新增到StringBuilder(字串變數,執行緒不安全,單執行緒下效率比較高)物件中,然後再利用Jackson的核心操作類ObjectMapper類把json字串轉化為user物件返回。

  第二步:編寫Action類

package com.action;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opensymphony.xwork2.ActionSupport;
import com.pojo.User;
import com.util.JsonUtil;

//接受json資料,列印json資料
public class UserAction3 extends ActionSupport {

    // 獲取response物件
    private HttpServletResponse response = ServletActionContext.getResponse();

    private HttpServletRequest request = ServletActionContext.getRequest();

    // 返回的結果集,必須提供getter和setter方法
    String result = null;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    // 返回json資料(利用jackson完成java物件與json的轉化)
    public String myexcute3() {

        response.setContentType("application/json;charset=UTF-8");
        try {
            User user = JsonUtil.accept(request);
            System.out.println(user);
            ObjectMapper json = new ObjectMapper(); // 新建json物件
            result = json.writeValueAsString(user); // user物件轉化為json字串
            System.out.println(result);
        } catch (JsonGenerationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return SUCCESS; // 返回SUCCESS標誌,主配置檔案根據result標籤的name來跳轉頁面或者輸出內容。
                        // Struts2的常量(SUCCESS、NONE、ERROR、INPUT、LOGIN)
    }

}

   

這裡使用ServletActionContext類獲取了response和requset物件,並且結果集result提供相應的getter和setter方法。最後返回一個json字串。

 

(5)配置struts.xml

   

<action name="UserAction3" class="com.action.UserAction3" method="myexcute3">         
            <!-- 返回json型別資料 -->
                  
            <result name="success" type="json">               
                <param name="root">result</param>
            </result>
</action> 

同理,配置這個Action類。action請求名稱設定為UserAction3(要和ajax提交的路徑一致),全類路徑要書寫正確。<result>表示要返回的內容(或頁面)。相關配置上面已經解釋,這裡不多說。

 

(6)配置web.xml

   和上面一樣。配置一個struts2核心過濾器。

(7)執行程式

   

 

5. 總結

(1)從本次開發看出struts的優缺點。優點:支援外掛(比如json外掛),ajax支援,通過配置檔案,就可以掌握整個系統各個部分之間的關係。實現了MVC模式,層次結構清晰。減少配置(有預設值)。

(2)struts的缺點(通過本次開發):缺點:對servlet依賴比較強(我們用到了request和response),Action中取得從jsp中傳過來的引數時還是有點麻煩。

(3)其實本質上我們還是通過Jackson框架進行json與java物件的相互轉化,只不過要依賴於struts-json外掛。其實我們只是用符合struts2框架的規範,編寫了一些Action類,來響應客戶端的請求。其實和之前的編寫servlet效果類似。

(4)Jackson類庫其實還蠻好用的,不信你試試!

(5)如果有什麼錯誤歡迎各位大佬指出,在下一定洗耳恭聽!哈哈!

 

   本篇部落格原始碼連結:https://pan.baidu.com/s/1zUvZxO_eVahocHcjMsyOPA             提取碼:nn3g 

 <