Hibernate+Spring+Struts擴(kuò)展Struts 2(轉(zhuǎn))
Request是如何被處理的ActionServlet是Struts框架中唯一的Servlet,它負(fù)責(zé)處理所有request。無(wú)論何時(shí)接收到一個(gè)request,它都會(huì)先嘗試為當(dāng)前的request尋找一個(gè)sub-application。一旦一個(gè)sub-application被找到,ActionServlet就會(huì)為那個(gè)sub-application創(chuàng)建一個(gè)RequestProcessor對(duì)象,調(diào)用這個(gè)對(duì)象的process()方法并把HttpServletRequest和HttpServletResponse對(duì)象傳入。
RequestProcessor.process()就是大部分request被處理的地方。process()方法使用了Template Method模式實(shí)現(xiàn),其中有很多獨(dú)立的方法來(lái)執(zhí)行請(qǐng)求處理的每一步驟,這些方法將會(huì)在process方法中依次被調(diào)用。比如,將會(huì)有一個(gè)獨(dú)立的方法用來(lái)尋找當(dāng)前request對(duì)應(yīng)的ActionForm類,一個(gè)方法來(lái)檢查當(dāng)前用戶是否有執(zhí)行action mapping所必須的權(quán)限。這些給與我們極大的靈活性。在發(fā)布的Struts包中有一個(gè)RequestProcessor類提供了請(qǐng)求處理每一步驟的默認(rèn)實(shí)現(xiàn)。這就意味著你可以僅僅重寫(xiě)你感興趣的方法,其它的使用默認(rèn)的實(shí)現(xiàn)。舉例來(lái)說(shuō),默認(rèn)地Struts調(diào)用request.isUserInRole()來(lái)檢查用戶是否有權(quán)限執(zhí)行當(dāng)前的ActionMapping;這時(shí)如果你想通過(guò)查詢數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn),你所要做的就是重寫(xiě)processRoles()方法,通過(guò)查詢出的用戶是否擁有必須的權(quán)限來(lái)返回true或false。
首先我們將會(huì)看到缺省情況下,process()方法是如何實(shí)現(xiàn)的,然后我將會(huì)詳細(xì)解釋默認(rèn)的RequestProcessor類中的每一個(gè)方法,這樣你就可以決定哪一部分是你想要改變的。
public void process(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { // Wrap multipart requests with a special wrapper request = processMultipart(request); // Identify the path component we will // use to select a mapping String path = processPath(request, response); if (path == null) { return; } if (log.isDebugEnabled()) { log.debug("Processing a '" + request.getMethod() + "' for path '" + path + "'"); } // Select a Locale for the current user if requested processLocale(request, response); // Set the content type and no-caching headers // if requested processContent(request, response); processNoCache(request, response); // General purpose preprocessing hook if (!processPreprocess(request, response)) { return; } // Identify the mapping for this request ActionMapping mapping = processMapping(request, response, path); if (mapping == null) { return; } // Check for any role required to perform this action if (!processRoles(request, response, mapping)) { return; } // Process any ActionForm bean related to this request ActionForm form = processActionForm(request, response, mapping); processPopulate(request, response, form, mapping); if (!processValidate(request, response, form, mapping)) { return; } // Process a forward or include specified by this mapping if (!processForward(request, response, mapping)) { return; } if (!processInclude(request, response, mapping)) { return; } // Create or acquire the Action instance to // process this request Action action = processActionCreate(request, response, mapping); if (action == null) { return; } // Call the Action instance itself ActionForward forward = processActionPerform(request, response,action, form, mapping); // Process the returned ActionForward instance processForwardConfig(request, response, forward); } |
1、processMutipart():在這個(gè)方法中,Struts將會(huì)讀取request來(lái)檢查request的contentType是否是multipart/form-data。如果是的話,將會(huì)解析request并且將之包裝到HttpServletRequest中。當(dāng)你創(chuàng)建了一個(gè)HTML FORM用來(lái)提交數(shù)據(jù),那么request的contentType默認(rèn)就是application/x-www-form-urlencoded。但是如果你的form使用了file類型的input控件允許用戶上傳文件的話,你就必須將contentType改為multipart/form-data。如果是這樣的情況,你就不能再通過(guò)getParameter()來(lái)獲取用戶提交的數(shù)據(jù);你必須將request作為一個(gè)InputStream來(lái)讀取,并且自己解析它來(lái)獲得參數(shù)值。
2、processPath():在這個(gè)方法中,Struts將會(huì)讀取request的URI,來(lái)確定路徑元素,這個(gè)元素是用來(lái)獲取ActionMappint元素。
3、processLocale():在這個(gè)方法中,Struts將會(huì)為當(dāng)前request取得Locale,如果配置過(guò)的話,還可以將這個(gè)對(duì)象作為HttpSession中org.apache.struts.action.LOCALE屬性的值而保存。作為這個(gè)方法的副作用,HttpSession將會(huì)被創(chuàng)建,如果你不想創(chuàng)建的話,你可以在ControllerConfig中將locale屬性設(shè)為false,在struts-config.xml中象如下這樣:
<controller> <set-property property="locale" value="false"/> </controller> |
4、processContent():通過(guò)調(diào)用response.setContentType()來(lái)為response設(shè)置contentType。這個(gè)方法首先會(huì)嘗試從struts-config.xml配置中得到contentType。缺省情況下使用text/html。如果想覆蓋它,可以象如下這樣:
<controller> <set-property property="contentType" value="text/plain"/> </controller> |
5、processNoCache():如果配置是no-cache,Struts將會(huì)為每個(gè)response設(shè)置下面三個(gè)headers:
requested in struts config.xml response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 1); |
如果你想設(shè)置no-cache header,在struts-config.xml中加入下面信息:
<controller> <set-property property="noCache" value="true"/> </controller> |
6、processPreprocess():這個(gè)方法為預(yù)處理提供一個(gè)hook,可以在子類中覆蓋它。它的缺省實(shí)現(xiàn)沒(méi)有作任何事情,總是返回true。返回false的話將會(huì)終止當(dāng)前請(qǐng)求的處理。
7、processMapping():這個(gè)方法將會(huì)用路徑信息得到一個(gè)ActionMapping對(duì)象。也就是struts-config.xml文件中的<action>元素:
<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類的名稱和處理請(qǐng)求使用的ActionForm等等信息。它還包含當(dāng)前ActionMapping配置的ActionForwards信息。
8、processRoles():Struts web應(yīng)用提供了一個(gè)授權(quán)方案。也就是說(shuō),一旦一個(gè)用戶登入了容器,struts的processRoles()方法將會(huì)通過(guò)調(diào)用request.isUserInRole(),來(lái)檢查他是否有必須的角色來(lái)運(yùn)行一個(gè)給定的ActionMapping。
<action path="/addUser" roles="administrator"/> |
假設(shè)你有一個(gè)AddUserAction并且你只想讓administrator能夠增加新的user。你所要做的就是給你的AddUserAction元素增加一個(gè)role屬性,這個(gè)屬性的值為administrator。這樣,在運(yùn)行AddUserAction之前,這個(gè)方法會(huì)確保用戶擁有administraotr的角色。
9、processActionForm():每一個(gè)ActionMapping都一個(gè)相應(yīng)的ActionForm類。當(dāng)Struts處理一個(gè)ActionMapping的時(shí)候,它將會(huì)從<action>元素的name屬性中找出對(duì)應(yīng)的ActionForm類的名稱。
<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> |
在我們的例子中,它會(huì)先在request scope中檢查是否有一個(gè)org.apache.struts.action.DynaActionForm類的對(duì)象存在。如果有它將會(huì)使用這個(gè)對(duì)象,如果沒(méi)有它將會(huì)創(chuàng)建一個(gè)新的對(duì)象并把它設(shè)置在request scope。
10、processPopulate():在這個(gè)方法中,Struts將會(huì)用相匹配的request參數(shù)裝配ActionForm的實(shí)例變量。
11、processValidate():Struts將會(huì)調(diào)用你的ActionForm類的validate方法。如果你從validate()返回ActionErrors,它將會(huì)將user重定向到<action>元素的input屬性指定的頁(yè)面。
12、processForward()和processInclude():在這些方法中,Struts將會(huì)檢查<action>元素的forward或include屬性,如果找到了,將會(huì)把forward或include請(qǐng)求放置到配置的頁(yè)面中。
<action forward="/Login.jsp" path="/loginInput"/> <action include="/Login.jsp" path="/loginInput"/> |
你可以從這些方法的名字上猜測(cè)它們的不同:processForward()最終調(diào)用RequestDispatcher.forward(),而processInclude()調(diào)用RequestDispatcher.include()。如果你同時(shí)配置了forward和include屬性,它將會(huì)總是調(diào)用forward,因?yàn)閒orward先被處理。
13、processActionCreate():這個(gè)方法從<action>元素的type屬性中獲取獲得Action類的名字并且創(chuàng)建返回它的實(shí)例。在我們的例子中,它將會(huì)創(chuàng)建一個(gè)com.sample.NewContactAction類的實(shí)例。
14、processActionPerform():這個(gè)方法調(diào)用你的Action類的excute()方法,你的業(yè)務(wù)邏輯也就是在excute方法中。
15、processForwardConfig():你的Action類的excute()方法將會(huì)返回一個(gè)ActionForward對(duì)象,這個(gè)對(duì)象將指出哪個(gè)頁(yè)面是顯示給用戶的頁(yè)面。因此,Struts將會(huì)為那個(gè)頁(yè)面創(chuàng)建一個(gè)RequestDispatcher,并且調(diào)用RequestDispatcher.forward()。
上面的列表說(shuō)明了默認(rèn)的RequestProcessor實(shí)現(xiàn)在處理請(qǐng)求時(shí)每一步作的工作,以及執(zhí)行的順序。正如你所看到的,RequestProcessor是非常靈活的,允許你通過(guò)設(shè)置<controller>元素的屬性來(lái)配置它。舉例來(lái)說(shuō),如果你的應(yīng)用準(zhǔn)備生成XML內(nèi)容來(lái)代替HTML,你就可以通過(guò)設(shè)置controller元素的屬性來(lái)通知Struts這些情況。
posted on 2005-09-14 13:07 Victor 閱讀(519) 評(píng)論(0) 編輯 收藏 所屬分類: 開(kāi)源相關(guān)