一、屬性驅動
在目標 Action 類中,通過 setXxx() 方法來接收請求參數。
二、模型驅動
1.ParametersInterceptor 攔截器工作原理
ParametersInterceptor 會將請求參數賦值給值棧中棧頂的對象。默認情況下,棧頂對象是目標 Action 類。
2.modelDriven 攔截器工作原理
獲取目標 Action 對象,判斷是否實現了 ModelDriven 接口,若實現,則調用目標 Action 的 getModel(),將該方法返回的對象壓入棧頂。
3.PrepareInterceptor 攔截器工作原理
首先獲取目標Action方法的名字,首字母大寫後加上prepare或prepareDo前綴,看有沒有這個前綴方法,如果有則執行。
4.Struts2 通過 ParametersInterceptor.doIntercept(ActionInvocation) 方法調用 Action 類的 setXxx() 方法向目標 Action 類注入對應的屬性。
5.攔截器棧
說明:
攔截器:Struts 定義了很多攔截器,每個攔截器有各自的作用。可以在 struts-default.xml 文件中看到定義的這些攔截器。
攔截器棧:Struts2 將若干攔截器進行了不同的組合排序,使這些攔截器進行協同工作,這就是攔截器棧(interceptor-stack)。
Struts2在 struts-default.xml 文件中定義了很多攔截器棧。
如:basicStack,validationWorkflowStack,fileUploadStack,modelDrivenStack,chainStack,i18nStack,paramsPrepareParamsStack,defaultStack,completeStack,executeAndWaitStack
默認攔截器棧為:<default-interceptor-ref name="defaultStack"/>
6.攔截器棧的調用者
defaultStack 攔截器棧中引用了 18 個攔截器。由 StrutsActionProxy 進行了調用,實際是由 DefaultActionInvocation 進行的調用。
說明:
DefaultActionInvocation 對象在初始化的時候就加載了當前攔截器棧中的所有攔截器 List ,然後在調用 invoke() 方法時,遍歷了這個 List,然後依次調用每個攔截器的 interceptor() 方法,
調用完所有攔截器方法,然後再去調用目標方法。這就是 Struts 工作的流程。
7.使用 defaultStack 攔截器棧的缺點
在 defaultStack 攔截器棧中定義了 攔截器的執行順序。modelDriven 攔截器先於 params 攔截器執行。
進行修改操作時,需要先傳一個 id 過來,然後根據 id 去數據庫中查找,將該對象作為 ModelDriven 的 getModel() 返回,進行表單回顯。但顯然 defaultStack 不能完成。
8.paramsPrepareParamsStack 攔截器棧
在 paramsPrepareParamsStack 棧中,params prepare modelDriven params 這樣的執行順序,能滿足需求。
這樣在修改是時候就能先注入 id 了。然後根據 id 去數據庫中查找,並將該對象作為 ModelDriven 的 getModel() 返回。
但是還有問題是,在刪除的時候,不需要去調用 getModel() 方法。
這時候就需要用到 prepare 攔截器,
為每一個有需要的Action方法量身打造自己專屬的 prepareXxx() 方法,在這個方法中為 getModel() 方法准備模型。
還有一個問題,每一次請求都會調用 prepare() 這個空方法。我們可以通過配置讓他不執行這個方法。
<interceptors>
<interceptor-stack name="myStack">
<interceptor-ref name="paramsPrepareParamsStack">
<param name="prepare.alwaysInvokePrepare">false</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
9.最終的一個例子:
public class BookAction extends ActionSupport implements RequestAware,ModelDriven<Book>,Preparable {
private static final long serialVersionUID = 1L;
private Dao dao = new Dao();
private Map<String, Object> requestMap;
private Book book;
private Integer bookId;
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
@Override
public Book getModel() {
return this.book;
}
@Override
public void prepare() throws Exception {
}
public void prepareUpdate() {
this.book = dao.getBook(bookId);
}
public String update() {
dao.updateBook(book);
return "update-success";
}
public void prepareEditUI() {
this.book = dao.getBook(bookId);
}
public String editUI() {
return "editUI";
}
public String remove() throws Exception {
dao.removeBook(bookId);
return "remove-success";
}
public void prepareSave() {
this.book = new Book();
}
public String save() {
dao.saveBook(book);
return "save-success";
}
public String showList() throws Exception {
requestMap.put("bookList", dao.getBookList());
return "showList";
}
@Override
public void setRequest(Map<String, Object> request) {
this.requestMap = request;
}
}
推薦閱讀:
Struts中異步傳送XML和JSON類型的數據 http://www.linuxidc.com/Linux/2013-08/88247.htm
Struts2的入門實例 http://www.linuxidc.com/Linux/2013-05/84618.htm
Struts2學習筆記-Value Stack(值棧)和OGNL表達式 http://www.linuxidc.com/Linux/2015-07/120529.htm
struts2文件上傳(保存為BLOB格式) http://www.linuxidc.com/Linux/2014-06/102905.htm
Struts2的入門實例 http://www.linuxidc.com/Linux/2013-05/84618.htm
Struts2實現ModelDriven接口 http://www.linuxidc.com/Linux/2014-04/99466.htm
遇到的Struts2文件下載亂碼問題 http://www.linuxidc.com/Linux/2014-03/98990.htm
Struts2整合Spring方法及原理 http://www.linuxidc.com/Linux/2013-12/93692.htm
Struts2 注解模式的幾個知識點 http://www.linuxidc.com/Linux/2013-06/85830.htm
Struts 的詳細介紹:請點這裡
Struts 的下載地址:請點這裡