程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 淺談Struts2,struts2

淺談Struts2,struts2

編輯:JAVA綜合教程

淺談Struts2,struts2


學過SSH框架很長一段時間了,一直沒有很系統的總結一下,這裡先簡單談談Struts2。

 

為什麼要用Struts2?

 

這裡列舉一些Servlet的缺點:

1、每寫一個servlet在web.xml中都要做相應的配置。如果有多很servlet,會導致web.xml內容過於繁多。

2、這樣的結構不利於分組開發。

3、在servlet中,doGet方法和doPost方法有HttpServletRequest和HttpServletResponse參數。這兩個參數與容器相關,如果想在servlet中作單元測試,則必須初始化這兩個參數。

4、如果一個servlet中有很多個方法,則必須采用傳遞參數的形式,分解到每一個方法中。

 

而而而而而而而而而而。。。。先了解一下Struts2是什麼。

Struts2是一個遵循MVC的Web層框架。

 

先看一下基於Web的MVC三層架構:

 

這是一個MVC三層架構的基本模式,三層架構中的顯示層這裡是B/S結構的Web應用。而MVC就是Model、View、Controller。

說好的Struts2是一個Web層的MVC框架呢?在Struts2中MVC是什麼呢?

 

 

  Struts2利用過濾器,攔截客戶端的請求。客戶端發送請求,經過struts2的過濾器,將HttpServletRequest參數和HttpServletResponse參數封裝,利用java反射機制將請求分派給映射的Action。根據Action的執行結果,轉向其他Action或jsp頁面

 

  Struts2 的Action實現了與Servlet API的解耦,使得在Action裡面不需要再直接去引用和使用HttpServletRequest與HttpServletResponse等接口。因而使得Action的單元測試更加簡單,而且強大的類型轉換也使得我們少做了很多重復的工作。

 

下面看一下Struts2的原理圖:

 

 

具體過程大致如下:

 

1、客戶端向Servlet容器(例如Tomcat)發送請求

2、這個請求經過一系列的過濾器(Filter)

3、接著FilterDispatcher(現已過時)被調用,FilterDispatcher詢問ActionMapper來決定這個請是否需要調用某個Action

4、如果ActionMapper決定需要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy

5、ActionProxy通過Configuration Manager詢問框架的配置文件,找到需要調用的Action類

6、ActionProxy創建一個ActionInvocation的實例。

7、ActionInvocation實例使用命名模式來調用,在調用Action的過程前後,涉及到相關攔截器(Intercepter)的調用。(此處采用了AOP,一系列的攔截器即通知,Action的方法為切入點)

8、Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果通常是(但不總是,也可 能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版。在表示的過程中可以使用Struts2 框架中繼承的標簽。在這個過程中需要涉及到ActionMapper

 

  在上述過程中所有的對象(Action,Results,Interceptors,等)都是通過ObjectFactory來創建的。

 

  FilterDispatcher是早期struts2的過濾器,2.1.3後使用StrutsPrepareAndExecuteFilter。StrutsPrepareAndExecuteFilter,prepare進行配制的導入;execute表示進行過濾,指doFilter方法,即將request請求,轉發給對應的 action去處理。

 

上面是Struts2的基本原理,下面看一下Struts2使用主要涉及的幾個方面:攔截器,驗證,類型轉換,屬性驅動、模型驅動,OGNL。

 

攔截器

  

  Struts2自帶的攔截器有35個之多。例如:輸入驗證是由名為validation攔截器處理的,如果禁用該攔截器,輸入驗證將停止工作;文件上傳依靠名為fileUpload的攔截器。

  Struts2自帶的默認攔截器足以滿足絕大多數的應用程序的需要,但也可以自定義攔截器。

 

自定義攔截器


1、編寫一個類,實現com.opensymphony.xwork2.interceptor.Interceptor

2、主要實現public String intercept(ActionInvocation invocation) throws Exception{}方法

3、攔截器定義好後,要在配置文件中進行注冊:

<interceptors> 
    <interceptor name=" interceptorName" class="className"/>        
</interceptors>

 

4、配置文件中的動作,通過 <interceptor-ref name=" interceptorName "></interceptor-ref> 使用該攔截器.

  注意:一旦動作中使用了自定義的攔截器,那麼默認的就不起作用了。一般應該采用如下的做法:

<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name=" interceptorName"></interceptor-ref>

多個動作類都要使用的話,可以通過package來進行組合。

 


驗證

  

  有時候對於從客戶端傳來的數據需要驗證,例如登錄頁面,驗證用戶名不能為空,密碼也不能為空,並且長度不能小於6位數。


驗證的方法有分為以下幾種:

 

1、編程方式

 

 動作類中的所有方法進行驗證:

  步驟:

  a、動作類繼承ActionSupport

  b、覆蓋調用public void validate()方法

  c、在validate方法中,編寫不符合要求的代碼判斷,並調用父類的addFieldError(String fieldName,String errorMessage)

    如果fieldError(存放錯誤信息的Map)有任何的元素,就是驗證不通過,動作方法不會執行。Struts2框架會返回到name=input的result

  d、在name=input指定的頁面上使用struts2的標簽顯示錯誤信息。<s:fielderror/>


 動作類中指定的方法進行驗證:

  編寫步驟與上面相同,驗證方法書寫有要求:

  public void validateXxx() Xxx代表的是要驗證的動作方法名,其中要把動作方法名的首字母變為大寫。


2、基於XML配置文件的方式

 

  ①動作類中的所有方法進行驗證:

  在動作類的包中,建立一個名稱為:動作簡單類名-validation.xml ,比如要驗證的動作類名是UserAction UserAction-validation.xml,內容如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE validators PUBLIC
 3     "-//OpenSymphony Group//XWork Validator 1.0.3//EN"
 4     "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
 5 <validators>
 6     <field name="username">
 7         <!-- 內置驗證器都是定義好的,在xwork-core.jar com.opensymphony.xwork2.validator.validators包中的default.xml文件中 -->
 8         <field-validator type="requiredstring"><!-- 不能為null或者""字符串,默認會去掉前後的空格 -->
 9         <message>用戶名不能為空</message>
10         </field-validator>
11     </field>
12 </validators>    

 


  ②動作類中指定的方法進行驗證:

  配置文件的名稱書寫有一定要求:動作類名-動作名(配置文件中的動作名)-validation.xml 例如UserAction-user_add-validation.xml

 


3、自定義基於XML的驗證器

 

  a、編寫一個類,繼承FieldValidatorSupport類。

  b、在public void validate(Object object)編寫你的驗證邏輯,不符合要求的就向fieldErrors中放消息

  c、一定注冊驗證器才能使用

   在WEB-INF/classes目錄下建立一個名稱為validators.xml的配置文件,內容如下:

<validators>
    <validator name="strongpassword" class="wz.validators.StrongPasswordValidator"/>
</validators>

 

  d、日後就可以像使用Struts2提供的16個驗證器方式去使用了。

 

 

屬性驅動和模型驅動

 

 

屬性驅動


條件:

  1、頁面中name的屬性和action中的屬性必須保持一致。

  2、 Action中的屬性必須有get和set方法。

  3、滿足這兩個條件就實現了屬性驅動。

 

過程:

  1、 當執行所有的攔截器的時候,當前請求的action已經放在了對象棧棧頂。

  2、 放在對象棧的對象的特點是其屬性能夠直接訪問。

  3、 也就是說當執行ParameterInterceptor攔截器的時候,action的所有的屬性在棧頂。

  4、 所以只需要給棧頂的action的屬性賦值就可以了。

  5、 而ParameterInterceptor攔截器正好完成了此功能。

 


模型驅動

 

  假設在完成網站的某項功能時,在後台需要得到20多個屬性。如果用action中的屬性獲取值,就要在action中會寫20個屬性以及其set和get方法。這樣會導致action中的代碼結構不是很好。

  模型驅動很好的解決了這個問題。使用javaBean對象來封裝請求參數,實現ModelDriven接口並定義模型成員域即可。

例如:

 1 public class ModelDriverAction extends ActionSupport implements ModelDriven<User>{
 2     private User model = new User();
 3     public User getModel() {
 4         return this.model;
 5     }
 6 
 7     public String execute(){
 8         return "modeldriver";
 9     }
10 }

 

  當浏覽器提交對當前Action的請求時,先經過攔截器。其中有一個攔截器為ModelDrivenInterceptor,從這個源代碼可以看出,這個攔截器的作用就是獲取實現了ModelDriver接口的action的模型驅動。在這裡為user。然後把模型驅動利用push方法壓入到對象棧棧頂。這樣就能直接通過屬性進行回顯和賦值了。

 

到底是用屬性驅動和是模型驅動呢?

 

(1)最好統一整個系統中的Action使用的驅動模型,即要麼都是用屬性驅動,要麼都是用模型驅動。

(2)如果DB中的持久層的對象與表單中的屬性都是一一對應的話,那麼就使用模型驅動,代碼要整潔很多。

(3)如果表單的屬性不是一一對應的話,那麼就應該使用屬性驅動,否則,你的系統就必須提供兩個Bean,一個對應表單提交的數據,另一個用與持久層。

 


類型轉換

 

  從屬性驅動的角度考慮,中如果屬性中要求接受的不是String類型,而是其他類型呢?struts2將做自動的轉化。

  客戶端表單的每一項輸入之可能是一個String或一個String數組。在服務器端,必須先把這些String值轉換為特定的數據類型,才能進行相應的處理把請求參數映射到動作屬性的工作由Parameters攔截器負責,它是defaultStack攔截器棧的一員。所有的請求參數都是String類型,但並非所有的動作屬性都是String類型,所以每一種非String類型的動作屬性需要對相關的請求參數進行類型轉換。有些Struts2可以自動轉化,而有些需要我們手動編寫轉換的代碼。

 

具體方式:


1、編寫一個類,繼承com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter

2、覆蓋掉其中的public Object convertValue(Map<String, Object> context, Object value,Class toType)

  context:OGNL表達式的上下文
    value:實際的值。用戶輸入的都是字符串,但他是一個String數組。
    toType:目標類型

3、注冊類型轉換器

  3.1局部類型轉換器:只對當前的Action有效

    具體做法:在動作類相同的包中,建立一個名稱是“動作類名-conversion.properties”的配置文件,文件中增加以下內容:要驗證的字段=驗證器的類全名。例如:birthday=wz.convertor.DateConvertor


  3.2全局類型轉換器:對所有的Action都有效

    具體做法:在WEB-INF/classes目錄下,建立一個名稱為"xwork-conversion.properties"的配置文件,文件中增加以下內容:目標類型全名=驗證器的類全名。例如:java.util.Date=cn.itcast.convertor.DateConvertor


注意:如果轉換失敗,Struts2框架會尋找name=input的結果頁面

 

 

OGNL

 

  OGNL表達式是(Object-Graph Navigation Language)是對象圖形化導航語言。OGNL是一個開源的項目,struts2中默認使用OGNL表達式語言來顯示數據。與serlvet中的el表達式的作用是一樣的。

 

  提起OGNL就不得不提ValueStack了。ValueStack是一個接口,在struts2中使用OGNL表達式實際上是使用實現了ValueStack接口的類OgnlValueStack,這個類是OgnlValueStack的基礎。ValueStack貫穿整個action的生命周期。每一個action實例都擁有一個ValueStack對象。其中保存了當前action對象和其他相關對象。Struts2把ValueStack對象保存中名為struts.valueStack的request域中。

 

  當struts接受一個請求時,會迅速創建ActionContext,ValueStack,action。然後把action存放進ValueStack,所以action的實例變量可以被OGNL訪問

 

 

ActionContext.getContext()從ThreadLocal中得到本線程的ActionContext對象

actionContext對象可以獲取context、application、session、valueStack等對象。後三者其實是從context中取出的。

ActionContext的成員域contextOgnlContext對象,即ValueStack中的context對象

context對象中存放request、session、application、parameters、attr等map以及ValueStack等對象

 

 

context map與valueStack的關系:

1、context中有一個鍵值對,key=com.opensymphony.xwork2.util.ValueStack.ValueStack,value=valueStack,即valueStack

2、valueStack中成員域包括CompoundRoot  root和OgnlCotext context;。沒錯,就是上面的context。

3、而ActionContext中的成員域context,就是上面的context。

 

下面是ActionContext中context對象的內容,注意看地址。

 

暫時就這麼多吧。以上

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