程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 詳解Java的Struts2框架的構造及其數據轉移方法

詳解Java的Struts2框架的構造及其數據轉移方法

編輯:關於JAVA

詳解Java的Struts2框架的構造及其數據轉移方法。本站提示廣大學習愛好者:(詳解Java的Struts2框架的構造及其數據轉移方法)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java的Struts2框架的構造及其數據轉移方法正文


Struts2的構造

1.為何要應用框架?

(1)框架主動完成了許多零碎的義務

關於Struts2來講,它贊助我們便利地完成了數據類型轉換、數據驗證、國際化等等
Web開辟中罕見的義務。還有Spring中年夜量應用的Template形式,都是在讓我們的開辟
進程加倍主動化、智能化。應用框架就是防止從新創造輪子,從新復制這些模板代碼。
框架讓我們將精神更多地放在更高等其余成績上,而不是罕見任務流和基本義務上。

(2)應用框架就是優雅地繼續了框架面前的架構

框架面前的架構平日界說了一系列的任務流程,我們要做的就是將特定運用的代碼
依靠到這套流程上,如許便可以享用到框架帶來的各種利益了。有些時刻我們也能夠
對抗框架的架構規矩,但框架平日以一種很難被謝絕的方法供給它的架構。如斯簡略
便可以優雅地繼續一個優良的架構,並且是收費的,何樂而不為呢?

(3)應用框架更輕易找到練習有素的人

我之前地點公司全部項目簡直都沒有效過甚麼框架,從Service辦事的查找(相似JNDI)
到日記打印(相似Log4j),再到數據庫銜接池(相似DBCP),全都是外部人員本身
完成的。一來是由於項目比擬老,其時能夠還沒有甚麼開源框架可供應用,二來也是由於
公司守舊的戰略,擔憂應用不穩固的開源框架能夠會給項目帶來風險。這在其時的情況下
或許是沒錯的,公司高層天然會從更年夜的視角來斟酌全部項目。

然則當項目逐步宏大起來,同時世界上優良的開源框架愈來愈多時,假如不克不及實時重構
並引入一些成熟的開源框架,最初的成果能夠就是新招來的開辟人員必需從頭開端進修
這個龐雜的體系(都是外部體系,網上也沒有文檔贊助),還要當心外部框架的各種Bug,
本錢真是太高了。

(4)外部框架跟不下行業的成長

後面說到了外部框架的Bug。關於開源框架,能夠會有框架開創者團隊、年夜批的開源喜好者、
開源社區來支撐。國民的力氣是無限的,Bug的修復速度可想而知,這點從比來開源後的
TextMate的Bug修復過程便可以看出了。許多棄捐了良久的Bug在開源後被喜好者們敏捷
處理,而外部框架呢?在現在開辟他的人員分開公司後,在沒有嚴重Bug時乃至都不會有人
去讀他的源代碼吧,差距可見一斑!

(5)固然應用框架也不是一本萬利的工作

後面也提到過,應用不成熟的框架是有風險的,關於一個不是那末保守的項目照樣守舊為好。
(除非這是一群自在沒拘謹的技巧狂熱份子,可以自行決議應用甚麼框架,那真是幸福的事)
就像我之前用過的Java的HA高可用性辦事Sequioa一樣,這個框架終究不再被開辟公司供給支撐
了,這時候風險就更年夜了。

另外,應用一些不罕見的框架時還要留意框架源碼的License協定,不要在項目中隨便援用、
修正框架的源碼以避免惹起不用要的司法膠葛。


2.Struts2面前的架構

既然後面曾經剖析了框架的這麼多利益,那我們天然會開端進修應用Struts2了。但應用Struts2
會繼續甚麼樣的優雅架構呢?其實從較高的籠統條理上看,它仍然是我們熟習的MVC形式。

對應之前HelloWorld的例子來看,掌握器C(FilterDispatcher)也就是我們在web.xml中聲明的
Struts2焦點類。而模子M就是我們的NewsAction舉措類。而視圖V天然就是news.jsp了。模子
的概念仿佛有些隱約,甚麼是模子呢?其實這個聽起來很名詞的概念在Struts2中既包括了靜態
從Web前端傳來的營業數據,也包括了營業邏輯的完成。

有人能夠會說這類架構沒甚麼新意嘛,MVC框架有許多,這跟其他框架有甚麼差別呢?讓我們
站在低一級其余籠統條理上剖解Struts2,看看它有甚麼不同凡響。

乍看非常龐雜,假如只從用戶角度來看,在開辟時我們只須要完成黃色的部門,也就是我們
HelloWorld實例中的struts.xml,NewsAction和news.jsp。這就是我們要做的全體,就如後面
說的,只須要做很少的工作,我們就成了這個優良架構的一部門。

如今來看其他部門。FilterDispatcher就是我們設置裝備擺設在web.xml中的Servlet過濾器,這是Struts2
的進口,一切Struts2的Web運用都要如許設置裝備擺設。接上去藍色和綠色的部門就是Struts2的焦點
了,可以說這些類都是Struts2的開辟人員精心設計架構的。

(1)客戶端發送要求,J2EE容器解析HTTP包,將其封裝成HttpServletRequest。

(2)FilterDispatcher攔阻到這個要求,並依據要求途徑到ActionMapper中查詢決議挪用哪一個Action。

(3)依據ActionMapper的前往成果,FilterDispatcher拜托ActionProxy去struts.xml中找到這個Action。

(4)ActionProxy創立一個ActionInvocation,開端對Interceptor和Action停止遞歸挪用。

(5)各個Interceptor完成各自義務

(6)真正對Action的挪用,前往成果途徑

(7)Result對象將前往數據輸入到流中

(8)前往HttpServletResponse給J2EE容器,容器發送HTTP包到客戶端。

這就是Struts2的履行流程,焦點對象是ActionInvocation和Interceptor,和還未引見的ActionContext。
ActionInvocation是全部流程的總調劑,它跟Spring AOP中的Invocation對象很像。而Interceptor有許多
都是Struts2自帶的,最主要的是保留要求參數,並將前台的數據傳遞到Action的成員變量上。

而ActionContext就是保留這些數據的全局高低文對象,最主要的是用來保留Action實例的ValueStack。
所謂全局是指ActionContext可以在Action和Result中拜訪,其實它是ThreadLocal類型。每一個要求線程
都邑有本身的Action和ActionContext實例。

可以說進修Struts2重要就是進修:

(1)讓Interceptor和Action合營完成義務。

(2)將前台數據保留到Action中。

(3)Result經由過程ValueStack從Action中獲得前往數據。


3.Struts2與Struts1的分歧點

從下面的履行流程曾經可以看出Struts1和2的偉大差別。

(1)ActionForm哪去了?Action照樣誰人Action嗎?

最顯著的就是我們在全部流程中都看不到ActionForm對象了,並且Action固然照樣叫這個名字,然則
看起來曾經跟Struts1中的Action完整分歧了。

起首ActionForm被擯棄了,早年台傳來的數據曾經可以保留就任意POJO了。先存到ActionForm再復制
到Dto對象的日子曾經是曩昔了。第二,這個POJO實際上是Action對象中的一個成員變量。這在Struts1
中一切要求同享一個Action實例時是弗成能的,如今Struts2會為每一個要求都創立一個Action實例,所以
如許做是行得通的。第三,固然如許可行,可是看起來似乎Action作為MVC中的模子M既保留數據,又
包括了營業邏輯,這是否是不良的設計啊?其實細心想一想,如許的設計很便利,我們曾經獲得了數據,
直接便可以去操作Service層了。Action的職責看似多了,其實其實不多。

(2)前端Servlet怎樣釀成了Filter?

我們曉得Struts1和Spring MVC都是經由過程前端Servlet來作為進口的,為何Struts2要用Servlet的過濾器呢?
由於Struts2是基於Webwork焦點的,與Struts1曾經完整分歧了。Webwork可以說下降了運用法式與J2EE
API的耦合,好比將ActionServlet改成Servlet的Filter,再好比對HttpServletRequest/Response的直接拜訪,
又如任何POJO都能擔負ActionForm的腳色,任何類不消完成Action接口便可以作為Action應用等等,
是以Struts2也繼續了這類優良的非侵入式設計。

這點與Spring的設計思惟有些相像。好比那些Ware接口,不關懷的Bean完整不須要完成,盡可能下降運用
法式代碼與框架的耦合。侵入性切實其實是框架設計時要斟酌的一個主要身分。

(3)Filter、Action、Result間的粘合劑OGNL

下圖可以清楚清楚明了地展現出OGNL是若何融入Struts2框架的。

在輸出頁面InputForm.html和前往頁面ResultPage.jsp應用Struts2標簽中拜訪Action中的數據是如斯便利,
OGNL使拜訪ValueStack中保留的Action的屬性就像拜訪ValueStack本身的屬性一樣便利。

對OGNL的年夜量應用是Struts2的一年夜特點。包含前台標簽傳值到Action,Result從Action中取值等都邑年夜量
用到OGNL。而OGNL中年夜量用到了反射,我想或許這是Struts2機能不如Struts1的一個緣由吧。究竟取得了
靈巧而低耦合的架構的同時是要支付必定價值的。

(4)Interceptor的強是無敵的強

Struts2中另外一個壯大的特征就是Interceptor攔阻器了。Struts2內建了年夜量的攔阻器,攔阻器使年夜量代碼可以
反復應用,主動化了之前我們所說的零碎的義務,從而使Struts2到達了高程度的存眷分別。這真是AOP思惟
在框架中運用的范例!


Struts2三種數據轉移方法
Struts2供給了JavaBean屬性,JavaBean對象,ModelDriven對象三種方法來保留HTTP要求中的參數。上面經由過程一個最多見的
登錄的例子來看下這三種數據轉移方法。頁面代碼很簡略,提交表單中包括有效戶名和暗碼,在Action中獲得這兩個參數從而
驗證用戶能否登錄勝利。

1、JavaBean屬性

<%@ page contentType="text/html;charset=UTF-8" %> 
 
<html> 
 
<head></head> 
 
<body> 
  <h1>登錄頁</h1> 
   
  <form action="/cdai/login" method="post"> 
   
    <div> 
      <label for="username">稱號:</label> 
      <input id="username" name="username" type="textfield"/> 
    </div> 
     
    <div> 
      <label for="password">暗碼:</label> 
      <input id="password" name="password" type="password"/> 
    </div> 
     
    <div> 
      <label for="rememberMe"> 
        <input id="rememberMe" name="rememberMe" type="checkbox"/> 記住我 
      </label> 
      <input type="submit" value="登錄"></input> 
    </div> 
     
  </form> 
   
</body> 
 
</html> 

package com.cdai.web.ssh.action; 
 
import com.cdai.web.ssh.request.LoginRequest; 
import com.cdai.web.ssh.service.UserService; 
import com.opensymphony.xwork2.Action; 
import com.opensymphony.xwork2.ModelDriven; 
 
public class LoginAction implements Action { 
 
  private String username; 
   
  private String password; 
   
  private UserService userService; 
   
  @Override 
  public String execute() { 
     
    System.out.println("Login action - " + request); 
     
    return SUCCESS; 
  } 
 
  public String getUsername() { 
    return request; 
  } 
 
  public void setUsername(String username) { 
    this.username = username; 
  } 
   
  public String getPassword() { 
    return request; 
  } 
 
  public void setPassword(String Password) { 
    this.Password = Password; 
  } 
   
} 

這類方法比擬簡明,直接將表單中的參數保留到Action中的屬性中。Action在驗證時能夠還須要將用戶名和暗碼再封裝成Dto的
情勢傳給Service層停止驗證。所認為甚麼不更進一步,直接將用戶名和暗碼保留到Dto中。


2、JavaBean對象

<%@ page contentType="text/html;charset=UTF-8" %> 
 
<html> 
 
<head></head> 
 
<body> 
  <h1>登錄頁</h1> 
   
  <form action="/cdai/login" method="post"> 
   
    <div> 
      <label for="username">稱號:</label> 
      <input id="username" name="request.username" type="textfield"/> 
    </div> 
     
    <div> 
      <label for="password">暗碼:</label> 
      <input id="password" name="request.password" type="password"/> 
    </div> 
     
    <div> 
      <label for="rememberMe"> 
        <input id="rememberMe" name="rememberMe" type="checkbox"/> 記住我 
      </label> 
      <input type="submit" value="登錄"></input> 
    </div> 
     
  </form> 
   
</body> 
 
</html> 
package com.cdai.web.ssh.action; 
 
import com.cdai.web.ssh.request.LoginRequest; 
import com.cdai.web.ssh.service.UserService; 
import com.opensymphony.xwork2.Action; 
import com.opensymphony.xwork2.ModelDriven; 
 
public class LoginAction implements Action { 
 
  private LoginRequest request; 
   
  private UserService userService; 
   
  @Override 
  public String execute() { 
     
    System.out.println("Login action - " + request); 
     
    return SUCCESS; 
  } 
 
  public LoginRequest getRequest() { 
    return request; 
  } 
 
  public void setRequest(LoginRequest request) { 
    this.request = request; 
  } 
   
} 

如許便可以很便利地直接挪用Service層了。然則有一個小缺陷就是如許加深了頁面參數名的深度,只要為參數名加上request
前綴(Action中的屬性名)能力使Struts2經由過程OGNL將表單中的參數准確保留到request對象中。


3、ModelDriven對象

<%@ page contentType="text/html;charset=UTF-8" %> 
 
<html> 
 
<head></head> 
 
<body> 
  <h1>登錄頁</h1> 
   
  <form action="/cdai/login" method="post"> 
   
    <div> 
      <label for="username">稱號:</label> 
      <input id="username" name="username" type="textfield"/> 
    </div> 
     
    <div> 
      <label for="password">暗碼:</label> 
      <input id="password" name="password" type="password"/> 
    </div> 
     
    <div> 
      <label for="rememberMe"> 
        <input id="rememberMe" name="rememberMe" type="checkbox"/> 記住我 
      </label> 
      <input type="submit" value="登錄"></input> 
    </div> 
     
  </form> 
   
</body> 
 
</html> 

package com.cdai.web.ssh.action; 
 
import com.cdai.web.ssh.request.LoginRequest; 
import com.cdai.web.ssh.service.UserService; 
import com.opensymphony.xwork2.Action; 
import com.opensymphony.xwork2.ModelDriven; 
 
public class LoginAction implements Action, ModelDriven<LoginRequest>  
{ 
 
  private LoginRequest request = new LoginRequest(); 
   
  private UserService userService; 
   
  @Override 
  public String execute() { 
     
    System.out.println("Login action - " + request); 
     
    return SUCCESS; 
  } 
 
  @Override 
  public LoginRequest getModel() { 
    return request; 
  } 
   
} 

這類方法要多完成一個ModelDriven接口,將ModelDriven供給的對象也保留到ValueStack上,從而使前台頁面可以直接經由過程
username和password屬性名來界說表單的參數名了。

三種方法詳細采取哪一種不克不及混為一談,照樣看項目標詳細需求再本身定吧!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved