ActionServlet是Struts架構裡唯一一個Servlet,它負責處理所有請求。它無論何時收到一個請求,都會首先試著為現有請求找到一個 子應用。一旦子應用被找到,它會為其產生一個RequestProcessor對象,並調用傳入HttpServletRequest和 HttpServletResponse為參數的process()方法。
大部分請處理都是在 RequestProcessor.process()發生的。Process()方法是以模板方法(Template Method)的設計模式來實現的,其中有完成request處理的每個步驟的方法;所有這些方法都從process()方法順序調用。例如,尋找當前請 求的ActionForm類和檢查目前使用者是否有許可權執行action mapping都有幾個單獨的方法。這給我們提供了極大的彈性空間。Struts的RequestProcessor對每個請求處理步驟都提供了預設的實 現方法。這意味著,你可以重寫你感興趣的方法,而其餘剩下的保留預設實現。例如,Struts預設調用request.isUserInRole()檢查 使用者是否有許可權執行當前的ActionMapping,但如果你需要從資料庫中尋找,那麼你要做的就是重寫processRoles()方法,並根據使用者 角色返回true 或 false。
首先我們看一下process()方法的預設實現方式,然後我將解釋RequestProcessor類裡的每個預設的方法,以便你決定要修改請求處理的哪一部分。
1、processMultipart(): 在這個方法中,Struts讀取request以找出contentType是否為 multipart/form-data。假如是,則解析並將其打包成一個實現HttpServletRequest的包。當你成生一個放置資料的 HTML FORM時,request的contentType預設是application/x-www-form-urlencoded。但是如果你的form 的input類型是FILE-type允許使用者上傳檔案,那麼你必須把form的contentType改為multipart/form-data。如 這樣做,你永遠不能通過HttpServletRequest的getParameter()來讀取使用者提交的form值;你必須以 InputStream的形式讀取request,然後解析它得到值。
2、processPath(): 在這個方法中,Struts將讀取request的URI以判斷用來得到ActionMapping元素的路徑。
3、processLocale(): 在這個方法中,Struts將得到當前request的Locale;Locale假如被配置,將作為 org.apache.struts.action.LOCALE屬性的值被存入HttpSession。這個方法的附作用是HttpSession會被 建立。假如你不想此事發生,可將在struts-config.xml 檔案裡ControllerConfig的local屬性設定為false,如下:<controller>
<set-property property="locale" value="false"/>
</controller>
4、processContent():通過調用response.setContentType()設定response的contentType。這個方法首先會試著的得到配置在struts-config.xml裡的contentType。預設為text/html,重寫方法如下:<controller>
<set-property property="contentType" value="text/plain"/>
</controller>
5、processNoCache():Struts將為每個response的設定以下三個header,假如已在struts 的config.xml將配置為no-cache。response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 1);
假如你想設定為no-cache header,在struts-config.xml中加如以下幾行<controller>
<set-property property="noCache" value="true"/>
</controller>
6、processPreprocess():這是一個一般意義的預先處理hook,其可被子類重寫。在RequestProcessor裡的實現什麼都沒有做,總是返回true。如此方法返回false會插斷要求處理。
7、processMapping():這個方法會利用path資訊找到ActionMapping對象。ActionMapping對象在struts-config.xml file檔案裡表示為<action>Code
<action path="/newcontact" type="com.sample.NewContactAction" name="newContactForm" scope="request">
<forward name="sucess" path="/sucessPage.do"/>
<forward name="failure" path="/failurePage.do"/>
</action>
ActionMapping元素包含了如Action類的名稱及在請求中用到的ActionForm的資訊,另外還有配置在當前ActionMapping的裡的ActionForwards資訊。
8、processRoles(): Struts的web 應用安全提供了一個認證機制。這就是說,一旦使用者登入到容器,Struts的processRoles()方法通過調用request.isUserInRole()可以檢查他是否有許可權執行給定的ActionMapping。<action path="/addUser" roles="administrator"/>
假如你有一個AddUserAction,限制只有administrator許可權的使用者才能新添加使用者。你所要做的就是在AddUserAction 的action元素裡添加一個值為administrator的role屬性。
9、processActionForm():每個ActionMapping都有一個與它關聯的ActionForm類。struts在處理ActionMapping時,他會從<action>裡name屬性找到相關的ActionForm類的值。Code
<form-bean name="newContactForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="firstName" type="java.lang.String"/>
<form-property name="lastName" type="java.lang.String"/>
</form-bean>
在這個例子裡,首先會檢查org.apache.struts.action.DynaActionForm類的對象是否在request 範圍內。如是,則使用它,否則建立一個新的對象並在request範圍內設定它。
10、processPopulate()::在這個方法裡,Struts將匹配的request parameters值填入ActionForm類的執行個體變數中。
11、processValidate():Struts將調用ActionForm的validate()方法。假如validate()返回ActionErrors,Struts將使用者轉到由<action>裡的input屬性標示的頁面。
12、processForward() and processInclude():在這兩個方法裡,Struts檢查<action>元素的forward和include屬性的值,假如有配置,則把forward和include 請求放在配置的頁面內。<action forward="/Login.jsp" path="/loginInput"/>
<action include="/Login.jsp" path="/loginInput"/>
你 可以從他們的名字看出其不同之處。processForward()調用 RequestDispatcher.forward(),,processInclude()調用 RequestDispatcher.include()。假如你同時配置了orward 和include 屬性,Struts總會調用forward,因為forward,是首先被處理的。
13、processActionCreate():這個方法從<action>的type屬性得到Action類名,並建立返回它的執行個體。在這裡例子中struts將建立一個com.sample.NewContactAction類的執行個體。
14、processActionPerform():這個方法調用Action 類的execute()方法,其中有你寫入的商務邏輯。
15、processForwardConfig():Action類的execute()將會返回一個ActionForward類型的對象,指出哪一頁面將展示給使用者。因此Struts將為這個頁面建立RequestDispatchet,然後再調用RequestDispatcher.forward()方法。
以 上列出的方法解釋了RequestProcessor在請求處理的每步預設實現及各個步驟執行的順序。正如你所見,RequestProcessor很有 彈性,它允許你通過設定<controller>裡的屬性來配置它。例如,假如你的應用將產生XML內容而不是HTML,你可以通過設定 controller的某個屬性來通知Struts。