Struts2框架 action實現Preparable接口後不再調用set方法進行屬性賦值

我的struts2使用的是2.3.16.3版本的,web配置struts2的監聽如下

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>struts-default.xml,struts-plugin.xml,config/struts-config/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>actionPackages</param-name>
      <param-value>com.founder.rk</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>*.action</url-pattern>
  </filter-mapping>

Struts2中package配置如下

<package name="global" extends="struts-default,json-default">
		<interceptors>			
			<interceptor-stack name="SMInterceptorStack">
				
				<interceptor-ref name="defaultStack"></interceptor-ref>
				
			</interceptor-stack>
		</interceptors>
		<default-interceptor-ref name="SMInterceptorStack"></default-interceptor-ref>
		<global-results>
			<result name="login" type="redirect">/sm/frame/system/login/login.jsp</result>
			<result name="error">/sm/frame/system/errorReport/error500.jsp</result>
			<result name="error_nologin">/sm/frame/system/errorReport/errorNologin.jsp</result>
			<result name="error_nopage">/sm/frame/system/errorReport/error404.jsp</result>
		</global-results>		
</package>

action類繼承和實現瞭如下接口

public class SjbflAction  extends ActionSupport implements Preparable,ModelDriven{

ModelDriven接口是使用模型封裝請求參數,Preparable接口是爲了在模型封裝之前構造model對象,代碼如下

@Override
	public SjbflVO getModel() {
		// TODO Auto-generated method stub
		return sjbfl;
	}

	@Override
	public void prepare() throws Exception {
		// TODO Auto-generated method stub
		System.out.println(request.getParameter("id"));
        //判斷是否傳遞參數id,如果有id,則根據id去數據庫獲取實例,沒有則創建一個新的
		if (isNullOrEmptyString(id)) {
			sjbfl = new SjbflVO();
		} else {
			sjbfl = sjbflService.getById(id);
		}
	}
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

就這樣,請求action的方法時我傳遞了id參數,但是發現action中prepare的方法中獲取屬性id爲空,我斷點調試了一下發現在執行action的prepare方法前沒有調用setId方法,沒有給id設置值,我檢查了好多地方都沒有發現問題所在,最後把實現Preparable接口給去掉後,set方法就自動調用了。
      後來我又查了一下Struts2的攔截器相關資料,結果代碼測試,發現其實是攔截器的問題,Struts2默認的攔截器棧

“defaultStack”如果action實現了preparable接口,action的執行順序是先執行prepare方法,再執行set方法,所以再prepare方法中屬性id是沒有被賦值的爲null,此時把默認的攔截器棧換成paramsPrepareParamsStack就解決了我遇到的上面的問題,代碼如下

<package name="global" extends="struts-default,json-default">
		<interceptors>
			<interceptor-stack name="SMInterceptorStack">
				<!-- 該攔截器棧,先調用action的set方法,再調用prepare方法,最後再調用一次set方法 -->
				<interceptor-ref name="paramsPrepareParamsStack" />
			</interceptor-stack>
		</interceptors>
		<default-interceptor-ref name="SMInterceptorStack"></default-interceptor-ref>
		<global-results>
			<result name="login" type="redirect">/sm/frame/system/login/login.jsp</result>
			<result name="error">/sm/frame/system/errorReport/error500.jsp</result>
			<result name="error_nologin">/sm/frame/system/errorReport/errorNologin.jsp</result>
			<result name="error_nopage">/sm/frame/system/errorReport/error404.jsp</result>
		</global-results>		
</package>

paramsPrepareParamsStack包含的攔截器如下:

   <interceptor-stack name="paramsPrepareParamsStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="datetime"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
   </interceptor-stack>

paramsPrepareParamsStack攔截器棧中的使用順序:

    params->prepare->model-driven->params

    Struts2的設計上要求modelDriven在params之前調用,而業務中prepare要負責準備model,準備model又需要參數,這就需要在prepare之前調用params攔截器設置相關參數,這個也就是創建paramsPrepareParamsStack的原因。

流程:

      1.params攔截器首先給action的相關參數賦值
      2.prepare攔截器執行prepare方法,prepare方法會根據參數,如id,去調用業務邏輯,設置model對象
      3.model-diven攔截器將model對象壓入值棧,這裏的model對象就是在prepare中創建
      4.params攔截器將參數值賦給model對象
      5.action的邏輯執行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章