1. 程式人生 > >struts1 Action原理與配置

struts1 Action原理與配置

今天臨時調到另外一個專案幫忙,三天時間修改一個功能,e(⊙o⊙)…,剛down下專案一看是struts1+Hibernate3,平時一直採用spring+springMvc+springData+Hibernate,之前只接觸過struts2還好久沒用了,只好先來看一下struts1的action配置了,又因為時間有限有限只好摘抄他人文章了,哈哈

 首先介紹下struts1工作原理:

  1.初始化:struts框架的總控制器ActionServlet是一個Servlet,它在web.xml中配置成自動啟動的

Servlet,在啟動時總控制器會讀取配置檔案(struts-config.xml)的配置資訊,為struts

中不同的模組初始化相應的物件。(面向物件思想)

2.傳送請求:使用者提交表單或通過URL向WEB伺服器提交請求,請求的資料用HTTP協議傳給web伺服器。

3.form填充:struts的總控制器ActionServlet在使用者提交請求時將資料放到對應的form物件中的成員

變數中。

4.派發請求:控制器根據配置資訊物件ActionConfig將請求派發到具體的Action,對應的formBean一併

傳給這個Action中的excute()方法。

5.處理業務:Action一般只包含一個excute()方法,它負責執行相應的業務邏輯(呼叫其它的業務模組)

完畢後返回一個ActionForward物件。伺服器通過ActionForward物件進行轉發工作。

6.返回響應:Action將業務處理的不同結果返回一個目標響應物件給總控制器。

7.查詢響應:總控制器根據Action處理業務返回的目標響應物件,找到對應的資源物件,一般情況下

為jsp頁面。

8.響應使用者:目標響應物件將結果傳遞給資源物件,將結果展現給使用者。

下面具體介紹一下struts1配置並配合簡單的例子簡單易懂:

    Action, ActionForm, ActionForward ,這三個物件構成了Struts 的核心。 


  Struts 最核心的控制器是ActionServlet ,該Servlet 攔截使用者請求,井將使用者請求轉入到Struts 體系內。

一、配置ActionServlet 




ActionServlet 是一個標準的Servlet ,在web.xml 檔案中配置,該Servlet 用於攔所有的HTTP 請求。 


在web.xml 檔案中配置ActionServlet 應增加如下片段:

<servlet>
    <!-- ActionServlet 的名 -->
    <servlet-name>actionSevlet</servlet-name>
    <!-- 配置Servlet 的實現類 -->
    <servlet-class>
        org.apache.struts.action.ActionServlet
    </servlet-class>
    <!-- 指定Struts 的第一個配置檔案 -->
    <init-param>
        <!-- 指定配置檔案的對映 -->
        <param-name>config</param-name>
        <param-value>/WEB-INF/struts-con工fgl.xml</param-value>
    </init-param>
    <!-- 指定Struts 的第二個配置檔案 -->
    <init-param>
        <!-- 指定配置檔案的對映 -->
        <param-name>config/wawa</param-name>
        <param-value>/WEB-INF/struts-config2.xml</param-value>
    </init-param>
    <!-- 將ActionServlet配置成自啟動Servlet -->
    <load-on-startup>2</load-on-startup>
</servlet>

二、配置ActionForm 


配置ActionForm ,必須包含ActionForm 類才行。Struts 要求ActionForm 必須繼承Struts 的基類: org.apache.struts.action.ActionForm,ActionForm 的實現非常簡單,該類只是一個普通的JavaBean,只要為每個屬性提供對應的setter 和getter 方法即可。根據前面的講解, ActionForm 用於封裝使用者的請求引數,而請求引數是通過JSP 頁面的表單域傳遞過來的。因此應保證ActionForm 的引數與表單域的名字相同。 


注意: JavaB ean 的引數是根據getter 、setter 方法確定的。如果希望有一個A 的屬性,則應該提供getA 和setA 的方法。 


(1)ActionForm的實現 


ActionForm 的屬性必須與JSP 頁面的表單域相同。本示例的表單包含如下兩個表單域: 


• usemame 


• password 


因此, ActionForm 必須繼承org.apache.struts.action.ActionForm,併為這兩個域提供對應的setter 和getter 方法,下面是ActionForm 的原始碼:

import org.apache.struts.action.ActionForm;
public class LoginForm extends ActionForm {
    private String username;
    private String password;

    // 表單域username對應的setter 方法
    /**
     * @return the username
     */
    public String getUsername() {
        return username;
    }

    /**
     * @param username
     *            the username to set
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password
     *            the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

}

(2)ActionForm 的配置 


所有的ActionForm 都被配置在struts-config.xml 檔案中,該檔案包括了一個form-beans 的元素,該元素內定義了所有的ActionForm,每個ActionForm 對應一個form-bean 元素。 


為了定義LoginForm. 必須在struts-config.xml檔案中增加如下程式碼:

<!-- 用於定義所有的ActionForm -->
<form-beans>
    <!-- 定義ActionForm,至少指定兩個屬性: name , type-->
    <form-bean name="loginForm" type="lee.LoginForm" />
</form-beans>

三、配置Action 


Action 的配置比ActionForm 相對複雜一點,因為Action 負責管理與之關聯的ActionForm. 它不僅需要配置實現類,還需要配置Action 的path 屬性,該屬性用於被用 


戶請求。對於只需在本Action 內有效的Forward. 還應在Action 元素內配置區域性Forward。 


(1)Action 的實現 


通過ActionForm. 可使Action 無須從HTTP 請求中解析引數。因為所有的引數都被封裝在ActionForm中,下面是Action 從AcitionForm 取得請求引數的原始碼:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class LoginAction extends Action {
    // 必須重寫該核心方法,該方法actionForm 將表單的請求引數封裝成值物件
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        //將ActionForm強制型別轉換為LoginForm
        LoginForm loginForm = (LoginForm) form;
        // 從ActionForm中解析出請求引數: username
        String username = loginForm.getUsername();
        // 從ActionForm中解析出請求引數: password
        String pass = loginForm.getUsername();
        //後面的處理與前一個示例的Action 相同。
        ...
    }
}

該Action 從轉發過來的ActionForm 中解析請求引數,對應的ActionForm 則由ActionServlet 在接收到使用者請求時,負責例項化。 


實際的過程是: ActionServlet 攔截到使用者請求後,根據使用者的請求,在配置檔案中查詢對應的Action , Action 的name 屬性指定了用於封裝請求引數的ActionForm; 然後ActionServlet 將建立預設的ActionForm 例項,並呼叫對應的setter 方法完成ActionForm的初始化。 


ActionServlet 在分發使用者請求時,也將對應ActionForm 的例項一同分發過來。 


(2)Action 的配置 


Action 需要配置如下幾個方面。 


• Action 的path: ActionServlet 根據該屬性來轉發使用者的請求,即將使用者請求轉發與之同名的Action 。同名的意思是:將請求的.do 字尾去掉,匹配Action 的path屬性值。 


• Action 的name: 此處的name 屬性並不是Action 本身的名字,而是與Action 關聯的ActionForm。因此該name 屬性必須是前面存在的ActionForm 名。 


• Action 的type: 該屬性用於指定Action 的實現類,也就是負責處理使用者請求的業 


務控制器。 


• 區域性Forward: Action 的轉發並沒有轉發到實際的JSP 資源,而是轉發到邏輯名,即Forward 名。在Action 內配置的Forward 都是區域性Forward (該Forward 只在該Action 內有效)。 


下面是該Action 的配置程式碼:

<!-- 該元素裡配置所有的Action -->
<action-mappings>
    <!-- 配置Action. 指定了path , name , type 等屬性 -->
    <action path="/login" type="lee.LoginAction" name="loginForm">
        <!-- 配置區域性Forward -->
        <forward name="welcome" path="/WEB-INF/jsp/welcome.jsp" />
        <forward name="input" path="/login.jsp" />
    </action>
</action-mappings>

四、配置Forward 


正如前面所講, Forward 分區域性Forward 和全域性Forward 兩種。前者在Action 裡配置,僅對該Action 有效:後者單獨配置,對所有的Action 都有效。 


配置Forward 非常簡單,主要需要指定以下三個屬性。 


• name: 該Forward 的邏輯名。 


• path: 該Forward 對映到的JSP 資源。 


• redirect: 是否使用重定向。 


區域性Forward 作為Action 的子元素配置;全域性Forward 配置在global-forwards 元素裡。 


下面是配置全域性Forward 的程式碼:

<!-- 配置全域性Forward -->
<global-forwards>
    <!-- 配置Forward物件的name 和path 屬性 -->
    <forward name="error" path="/WEB-INF/jsp/error.jsp" />
</global-forwards>

上面的配置程式碼中,配置了一個全域性Forward,該Forward 可以被所有的Action 訪問。通常,只將全域性資源配置成全域性Forward。當每個Action 在轉發時,首先在區域性Forward 中查詢與之對應的Forward,如果在區域性Forward 中找不到對應的Forward 物件,才會到全域性Forward 中查詢。因此,區域性Forward 可以覆蓋全域性Forward。 


下面提供了該應用的struts-config.xm1檔案的全部原始碼:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Struts 配置檔案的檔案頭,包含DTD 等資訊 -->
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<!--Struts 配置檔案的根元素 -->
<struts-config>
    <!--配置所有的ActionForm -->
    <form-beans>
        <!--配置第一個ActionForm,指定ActionForm的name 和type 屬性 -->
        <form-bean name="loginForm" type="lee.LoginForm" />
    </form-beans>
    <!--配置全域性Forward物件 -->
    <global-forwards>
        <!--該Forward物件的name 屬性為error. 對映資源為/WEB-INF/jsp/error.jsp -->
        <forward name="error" path="/WEB-INF/jsp/error.jsp" />
    </global-forwards>
    <!--此處配置所有的Action 對映-->
    <action-mappings>
        <!--配置Action 的path. type 屬性name 屬性配置Action 對應的ActionForm-->
        <action path="/login" type="lee.LoginAction" name="loginForm">
            <!--還配置了兩個區域性Forward. 這兩個區域性Forward僅對該Action有效-->
            <forward name="welcome" path="/WEB-INF/jsp/welcome.jsp" />
            <forward name="input" path="/login.jsp" />
        </action>
    </action-mappings>
</struts-config>

配置檔案詳解如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config.dtd">
<!-- struts-config.xml中的元素必須按照上述doc指令中的dtd文件定義順序書寫,本例即遵從了dtd定義順序 -->
<!-- struts-config是整個xml的根元素,其他元素必須被包含其內 -->
<struts-config>
<!--
   名稱:data-sources
   描述:data-sources元素定義了web App所需要使用的資料來源
   數量:最多一個
   子元素:data-source
-->
<data-sources>
   <!--
    名稱:data-source
    描述:data-source元素定義了具體的資料來源
    數量:任意多個
    屬性:
     @key:當需要配置多個數據源時,相當於資料來源的名稱,用來資料來源彼此間進行區別
     @type:可以使用的資料來源實現的類,一般來自如下四個庫
      Poolman,開放原始碼軟體
      Expresso,Jcorporate
      JDBC Pool,開放原始碼軟體
      DBCP,Jakarta
   -->
   <data-source key="firstOne" type="org.apache.commons.dbcp.BasicDataSource">
    <!--
     名稱:set-property
     描述:用來設定資料來源的屬性
     屬性:
      @autoCommit:是否自動提交 可選值:true/false
      @description:資料來源描述
      @driverClass:資料來源使用的類
      @maxCount:最大資料來源連線數
      @minCount:最小資料來源連線數
      @user:資料庫使用者
      @password:資料庫密碼
      @url:資料庫url
    -->
    <set-property property="autoCommit" value="true"/>
    <set-property property="description" value="Hello!"/>
    <set-property property="driverClass" value="com.mysql.jdbc.Driver"/>
    <set-property property="maxCount" value="10"/>
    <set-property property="minCount" value="2"/>
    <set-property property="user" value="root"/>
    <set-property property="password" value=""/>
    <set-property property="url" value="jdbc:mysql://localhost:3306/helloAdmin"/>
   </data-source>
</data-sources>

<!--
   名稱:form-beans
   描述:用來配置多個ActionForm Bean
   數量:最多一個
   子元素:form-bean
-->
<form-beans>
   <!--
    名稱:form-bean
    描述:用來配置ActionForm Bean
    數量:任意多個
    子元素:form-property
    屬性:
     @className:指定與form-bean元素相對應的配置類,一般預設使用org.apaceh.struts.config.FormBeanConfig,如果自定義,則必須繼承 FormBeanConfig
     @name:必備屬性!為當前form-bean制定一個全域性唯一的識別符號,使得在整個Struts框架內,可以通過該識別符號來引用這個ActionForm Bean。
     @type:必備屬性!指明實現當前ActionForm Bean的完整類名。
   -->
   <form-bean name="Hello" type="myPack.Hello">
    <!--
     名稱:form-property
     描述:用來設定ActionForm Bean的屬性
     數量:根據實際需求而定,例如,ActionForm Bean對應的一個登陸Form中有兩個文字框,name和password,ActionForm Bean中也有這兩個欄位,則此處編寫兩個form-property來設定屬性
     屬性:
      @className:指定與form-property相對應的配置類,預設是org.apache.struts.config.FormPropertyConfig,如果自定義,則必須繼承FormPropertyConfig類
      @name:所要設定的ActionForm Bean的屬性名稱
      @type:所要設定的ActionForm Bean的屬性值的類
      @initial:當前屬性的初值
    -->
    <form-property name="name" type="java.lang.String"/>
    <form-property name="number" type="java.lang.Iteger" initial="18"/>
   </form-bean>
</form-beans>

<!--
   名稱:global-exceptions
   描述:處理異常
   數量:最多一個
   子元素:exception
-->
<global-exceptions>
   <!--
    名稱:exception
    描述:具體定義一個異常及其處理
    數量:任意多個
    屬性:
     @className:指定對應exception的配置類,預設為org.apache.struts.config.ExceptionConfig
     @handler:指定異常處理類,預設為org.apache.struts.action.ExceptionHandler
     @key:指定在Resource Bundle種描述該異常的訊息key
     @path:指定當發生異常時,進行轉發的路徑
     @scope:指定ActionMessage例項存放的範圍,預設為request,另外一個可選值是session
     @type:必須要有!指定所需要處理異常類的名字。
     @bundle:指定資源繫結
   -->
   <exception
    key=""hello.error
    path="/error.jsp"
    scope="session"
    type="hello.HandleError"/>
</global-exceptions>

<!--
   名稱:global-forwards
   描述:定義全域性轉發
數量:最多一個
   子元素:forward
-->
<global-forwards>
   <!--
    名稱:forward
    描述:定義一個具體的轉發
    數量:任意多個
    屬性:
     @className:指定和forward元素對應的配置類,預設為org.apache.struts.action.ActionForward
     @contextRelative:如果為true,則指明使用當前上下文,路徑以“/”開頭,預設為false
     @name:必須配有!指明轉發路徑的唯一識別符號
     @path:必須配有!指明轉發或者重定向的URI。必須以"/"開頭。具體配置要與contextRelative相應。
     @redirect:為true時,執行重定向操作,否則執行請求轉發。預設為false
   -->
   <forward name="A" path="/a.jsp"/>
   <forward name="B" path="/hello/b.do"/>
</global-forwards>

<!--
   名稱:action-mappings
   描述:定義action集合
   數量:最多一個
   子元素:action
-->
<action-mappings>
   <!--
    名稱:action
    描述:定義了從特定的請求路徑到相應的Action類的對映
    數量:任意多個
    子元素:exception,forward(二者均為區域性量)
    屬性:
     @attribute:制定與當前Action相關聯的ActionForm Bean在request和session範圍內的名稱(key)
     @className:與Action元素對應的配置類。預設為org.apache.struts.action.ActionMapping
     @forward:指名轉發的URL路徑
     @include:指名包含的URL路徑
     @input:指名包含輸入表單的URL路徑,表單驗證失敗時,請求會被轉發到該URL中
     @name:指定和當前Acion關聯的ActionForm Bean的名字。該名稱必須在form-bean元素中定義過。
     @path:指定訪問Action的路徑,以"/"開頭,沒有副檔名
     @parameter:為當前的Action配置引數,可以在Action的execute()方法中,通過呼叫ActionMapping的getParameter()方法來獲取引數
     @roles:指定允許呼叫該Aciton的安全形色。多個角色之間用逗號分割。處理請求時,RequestProcessor會根據該配置項來決定使用者是否有呼叫該Action的許可權
     @scope:指定ActionForm Bean的存在範圍,可選值為request和session。預設為session
     @type:指定Action類的完整類名
     @unknown:值為true時,表示可以處理使用者發出的所有無效的Action URL。預設為false
     @validate:指定是否要先呼叫ActionForm Bean的validate()方法。預設為true
    注意:如上屬性中,forward/include/type三者相斥,即三者在同一Action配置中只能存在一個。
   -->
   <action path="/search"
    type="addressbook.actions.SearchAction"
    name="searchForm"
    scope="request"
    validate="true"
    input="/search.jsp">
    <forward name="success" path="/display.jsp"/>
   </action> 
</action-mappings>

<!--
   名稱:controller
   描述:用於配置ActionServlet
   數量:最多一個
   屬性:
    @bufferSize:指定上傳檔案的輸入緩衝的大小.預設為4096
    @className:指定當前控制器的配置類.預設為org.apache.struts.config.ControllerConfig
    @contentType:指定相應結果的內容型別和字元編碼
    @locale:指定是否把Locale物件儲存到當前使用者的session中,預設為false
    @processorClass:指定負責處理請求的Java類的完整類名.預設org.apache.struts.action.RequestProcessor
    @tempDir:指定檔案上傳時的臨時工作目錄.如果沒有設定,將才用Servlet容器為web應用分配的臨時工作目錄.
    @nochache:true時,在相應結果中加入特定的頭引數:Pragma ,Cache-Control,Expires防止頁面被儲存在可數瀏覽器的快取中,預設為false
-->
<controller 
   contentType="text/html;charset=UTF-8"
   locale="true"
   processorClass="CustomRequestProcessor">
</controller>
<!--
   名稱:message-resources
   描述:配置Resource Bundle.
   數量:任意多個
   屬性:
    @className:指定和message-resources對應的配置類.預設為org.apache.struts.config.MessageResourcesConfig
    @factory:指定資源的工廠類,預設為org.apache.struts.util.PropertyMessageResourcesFactory
    @key:
    @null:
    @parameter:
-->
<message-resources
   null="false"
   parameter="defaultResource"/>
<message-resources
   key="images"
   null="false"
   parameter="ImageResources"/>

<!--
   名稱:plug-in
   描述:用於配置Struts的外掛
   數量:任意多個
   子元素:set-property
   屬性:
    @className:指定Struts外掛類.此類必須實現org.apache.struts.action.PlugIn介面
-->
<plug-in
   className="org.apache.struts.validator.ValidatorPlugIn">
   <!--
    名稱:set-property
    描述:配置外掛的屬性
    數量:任意多個
    屬性:
     @property:外掛的屬性名稱
     @value:該名稱所配置的值
   -->
   <set-property 
    property="pathnames"
    value="/WEB-INF/validator-rules.xml,/WEB-INF/vlaidation.xml"/>
</plug-in>

</struts-config>
一、為struts配置web.xml 
1,配置ActionServlet(only one),使其接收應用程式收到的所有請求 
分為兩步,a:使用servlet元素配置servlet例項,做servlet-mapping 
<web-app> 
<servlet> 
<servlet-name>storefront</servlet-name> 
<servlet-class>完全限定的類名</servlet-class> 
</servlet> 
<servlet-mapping> 
<servlet-name>storefront</servlet-name> 
<url-pattern>*.do</url-pattern> 
</servlet-mapping> 
</web-map> 
2,配置初始化引數:init-param,以name/value表示<param-name><param-value> 
config :預設為/WEB-INF/struts-config.xml 
config/sub1:config/... 從附加的struts配置檔案中加在資程式sub1 
debug:servlet的除錯detail 
detail:Digester的除錯detail 
convertHack 
3,<taglib>使用struts提供的標記庫時必須配置包括 
<taglib-uri>識別web應用程式所使用的標記庫,必須是有效的 
<taglib-location>指定了標記庫描述檔案的位置 
4,<welcome-file-list>配置在web app中輸入有效的,但不完整的url所使用的default resource;不使用servlet對映 
<welcome-file>起始和結束都沒有/符號 
5,<error-page> 
(<error-code> <location>) 
<<exception-type><location> 
</error-page>

二、Struts配置檔案 
ApplicationConfig: 包含了struts配置檔案中的所有資訊 
1, <data-source> 
<set-property property=““ value=““/> 
<data-source> 
2,<form-beans> 
<form-bean name=“loginForm“ type=“完全限定的類名,是ActionForm的子類“> 
<form-property name=““ type=““/> 
</form-bean> 
<form-bean 
</form-beans> 
3,<global-exceptions> 
4,<global-forwards>

在Struts1.3中已經取消了<data-sources>標籤,也就是說只能在1.2版中配置,因為Apache不推薦在struts-config.xml中配置資料來源。所以建議不要在struts中配置資料來源,如果你用了hibernate或spring得話就可以在hibernate配置檔案或spring檔案配資料來源如果都沒用就到tomcat中配置