我的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的邏輯執行