Struts2技术详解
http://www.cnblogs.com/bettertanme/p/3388739.html
1, 當Action設置了某個屬性后,Struts將這些屬性封裝一個叫做Struts.valueStack的屬性里。獲取valueStack對象: ValueStack vs = (ValueStack) request.getAttribute("struts.valueStack");
 調用ValueStack 的vs.findValue("books")方法(books為Action中的屬性);
2, struts2的Action類是一個普通的POJO類(通常包含一個無參的execute方法)從而很 好的重用代碼。
4,struts2通常直接使用Action來封裝HTTP請求參數,所以Action中要定義與請求參數對應的屬性,并且為該屬性提供相應的 getter和setter方法。
5,即使Action需要處理的請求name和pass兩個HTTP請求參數,Action類也可以不包含name和pass屬性,因為系統(tǒng)是通過對應的 getter和setter方法來處理請求參數。而不是通過屬性來處理請求參數的。所以Action類是否包含name和pass屬性不重要, 重要的是需要setter和getter方法。
6,Action類的屬性,不僅可以封裝請求參數,還可以用于封裝處理結果,通過Struts2標簽來輸出對應的屬性值。如 <s:Property value="tip">。
7,ActionContext類。Struts2的Action并未直接與任何Servlet api耦合,從而更加方便測試該Action(可以通過脫離web容器測試Action)。但是對于Web應用的控制器來說,不訪問Servlet api 幾乎是不能的。例如跟蹤HTTP session狀態(tài)等。訪問的Servlet Api 就 是HttpServeltRequest、HttpSession、ServletContext,這三個類分別jsp內置對象中的request、session、application。Web應用中提供了一個ActionContext類,Struts2的Action可以通過該類來訪問Servlet api。
 該類的ActionContext提供getContext方法得到ActionContext實例,
 該類的方法:
 ①Object get(Object key),該方法類似于HttpServletRequest的getAttribute(String name)方法;
 ②Map getApplication(),返回Map對象,該對象模擬了應用的ServletContext的實例
 ③static ActionContext getContext(),靜態(tài)方法,獲得系統(tǒng)提供的ActionContext實例。
 ④Map getParameters()獲取所有的請求參數,類似于調用HttpServletRequest對象的getParammeterMap方法。
 ⑤Map getSession()該Map對象模擬了HttpSession實例。
 ⑥void setApplication(Map application)直接傳入一個Map實例,將該Map實例的key-value對轉換成application的屬性名、屬性值。類似的還有setSession(Map session)
 ⑦put(Object key, Object value)直接為HttpServletRequest設置屬性。相當于request.setAttribute(key,value).可通過EL表達式輸出。
8,ServletActionContext類(是ActionContext類的子類)。 雖然Struts2提供了ActionContext來訪問Servlet Api,但是這種訪問畢竟不能直接獲得Servlet Api實例,為了Action中 直接訪問Servlet api,Struts2提供了如下的接口:ServletContextAware、ServletRequestAware、ServletResponseAware 。如果Action實現這些接口,能分別直接訪問用戶請求的ServletContext、HttpServletRequest、HttpServletResponse實例。
 并且,為了直接訪問Servlet api。Struts2提供了一個ServletAction類。通過ServletActionContext類可以更加方便的地直接訪問Servlet api。這類的主要方法(全是static):
 ①getActionContext(HttpServletRequest req)得到當前的ActionContext實例。
 ②getActionMapping()得到ActionMapping實例(得到 action mapping為context)。
 ③getRequest()得到HttpServletRequest實例(Gets the HTTP servlet request object)。
 ④getResponse()得到HttpServletResponse實例(Gets the HTTP servlet response object.)
 ⑤getServletContext()得到ServletAction實例(Gets the servlet context.)
 ⑥getValueStack(HttpServletRequest req)得到ValueStack實例。
 ⑦setRequest(HttpServletRequest request)(Sets the HTTP servlet request object)相應的有setResponse(HttpServletResponse response)、setServletContext(ServletContext servletContext)。
9,雖然可以在Action類獲取HttpServletResponse,但如果希望通過HttpServletResponse來生成服務器響應是不可能的,因為Action只是控制器(它并不直接對瀏覽器生成任何相應)。即如果在Action中寫如下代碼:response.getWriter().println("hello world");
 是沒有意義的。
10,對于使用Struts2框架的應用而言,盡量不要讓超級鏈接鏈接到某個視圖資源,
 因為這種方式增加了額外的風險,推薦將所有請求都發(fā)給Struts2框架,讓該框架來處理用戶的請求,
 即使是簡單的超級鏈接。
11,邏輯視圖名是指:Action返回的字符串;物理視圖是指:頁面的實際名稱。
 Struts2通過配置邏輯視圖名和物理視圖之間的映射關系,一旦系統(tǒng)收到Action返回的某個邏輯視圖,系統(tǒng)就會把相應的物理視圖呈現給用戶。
12,默認值:如果配置<result../>元素時沒有指定location參數,系統(tǒng)將會把<result..>...<result../>中間的字符串當成實際視圖資源。如果沒有配置parse參數,則默認值為true(該參數指定實際視圖名是否可以使用OGNL表達式);如果沒有指定name屬性則默認值為Struts2的默認處理結果類型(dispacher).
13,歸納起來,Struts2內建支持結果類型如下(14):
 ①chain結果類型:Action鏈式處理結果類型。
 ②chart結果類型:用于整合JFreeChart的結果類型。
 ③dispatch結果類型:用于jsp整合的結果類型。
 ④freemarker結果類型:FreeaMarker整合的結果類型。
 ⑤httpheader結果類型:用于控制Http行為的結果類型。 
 ⑥jasper結果類型:用于JasperReports整合的結果類型。
 ⑦jsf結果類型:用于整合JSF整合的結果類型。
 ⑧redirect結果類型:用于直接跳轉到其他的URI的結果類型。
 ⑨redirectAction結果類型:用于直接跳轉到其他的Action的結果類型。
 ⑩stream結果類型:用于向瀏覽器返回一個InputStream(一般用于文件下載)。
 ⑾tiles結果類型:用于與Tiles整合的結果類型。
 ⑿velocity結果類型:用于與Velocity整合的結果類型。
 ⒀xslt結果類型:用于與XML/XSLT整合的結果類型。
 ⒁plainText結果類型:用于顯示某個頁面的原始代碼的結果類型。
14,【redirect】結果類型。
 這種結果類型與dispatch結果類型相對,dispatch結果類型是將請求Forward(轉發(fā))
 到指定的jsp資源。而redirect結果類型,則意味著將請求Redirect(重定向)
 到指定的視圖資源。
 dispatch結果類型與redirect結果類型的差別就是轉發(fā)和重定向的差別:
 重定向會丟失所有的請求參數和請求屬性---當然也會丟失Action的處理結果。
 使用redirect結果類型的效果是:系統(tǒng)將調用HttpServletResponse的sendRedirect(String)方法來重定向指定的視圖資源,這種重定向的效果就是重新產生一個請求。所以所有的請求參數、請求屬性、Action實例和Action中封裝的屬性全部丟失。
15,【redirectAction】結果類型.
 使用redirectAction結果類型時,系統(tǒng)將重新生成一個新的請求,
 只是該請求的URI不是一個具體的試圖資源,而是一個Action。因此前一個Action處理結果
 ,請求參數,請求參數都會丟失。
16,除了可以通過通配符來配置Action(result),還可以使用OGNL表達式,這種
 用法允許讓請求參數來決定結果。如:
 <action name="save" class="......." method="save">
 <result name="input">/..jsp</result>
 <result type="redirect" >edit.action?skillName=${currentSkill.name}</result>
 </action>
 對于上面的表達式語法,要求對應的Action實例里應該包含currentSkill屬性,且currentSkill屬性必須包含name屬性--否則,${currentSkill.name}表達式為null。
17,模型驅動:
 對于Struts1的ActionForm對象而言。它的唯一作用就是封裝請求參數,當Struts1攔截到用戶的請求后,Struts1負責將請求參數封裝成ActionForm對象。
 如果Struts2的開發(fā)者懷念這種開發(fā)方式,則可以使用Struts2提供的模型驅動模式,
 這種模式也通過專門的JavaBean來封裝請求參數。
 相比于Struts1的Action類,Struts2的Action承擔了太多的責任,既用于封裝來回請求的參數,也保護了控制邏輯---這種模式實在不太清晰。出于清晰的考慮,應該采用單獨的Model實例來封裝請求參數和處理結果,這就是所謂的模型驅動。
 作用:Struts2的模型對象可以封裝更多的信息,它不僅可以封裝用戶的請求參數,而且還可以封裝Action的處理結果。用單獨的JavaBean實例來貫穿MVC流程。
 使用模型驅動時,Action必須實現ModelDriven接口,且必須實現getModel方法,
 該方法用于把Action和與之相對應的Model實例關聯(lián)起來。
 簡單的說,模型驅動使用單獨的VO(值對象)來封裝請求參數和處理結果。
18,【屬性驅動】:
 使用屬性(Property)作為貫穿MVC流程的信息攜帶者,當然屬性無法獨立存在,他必須依附于一個對象,這個對象就是Action實例,
 簡單的說,屬性驅動使用Action實例來封裝請求參數和處理結果。
19,Struts2的【處理異常機制】:
 在execute方法中手動捕捉異常,當捕捉到特定的異常時,返回特定的視圖--但是
 這種方式很是繁瑣,需要在execute中書寫大量的catch塊,最大的缺點
 還在于異常與代碼耦合,一旦需要改變異常處理方式,必須修改代碼!
 Struts2提供了一種聲明式的異常處理方式。
 在輸出錯誤信息的jsp頁面,有兩種輸出方式:
 ①通過struts2標簽輸出異常對象的message屬性。<s:property value="exception.message"/>。
 ②通過struts2標簽輸出堆棧信息。<s:property value="exceptionStack"/>。
 注意:全局異常映射的result屬性通常不要使用局部結果,局部異常映射的result屬性可以使用全局結果,也可以不使用。
20,對于WEB應用而言,所有的請求參數都是字符串類型的。
21,【類型轉換器】:
 struts2的類型轉換器實際上是基于OGNL實現的,在OGNL項目中有一個TypeConverter接口,因其實現的方法過于麻煩,所以OGNL項目還提供了一個該接口的實現類:DefaultTypeConverter,通過繼承該類來實現自己的轉換器。
 實現自定義的類型轉換需要重寫DefaultTypeConverter類的convertValue方法。
22,上面的類型轉換器都是基于OGNL的DefaultTypeConverter類實現的,基于
 該類實現類型轉換器的時候時,將字符串轉化成符合類型要通過convertValue方法實現
 因此我們必須先通過toType參數來判斷轉換的方向,然后分別實現不同的轉換邏輯。
 為了簡化類型轉換的實現,struts2提供了一個StrutsTypeConverter抽象類(基于struts2的類轉換器)
 這個抽象類是DefaultTypeConverter類的子類.
23,對于以上的類型轉換,我們一直只處理字符串數組的第一個元素---我們都假設請求參數是單個值。實際上,必須考慮請求參數是字符數組的情形, 假設用戶信息的請求參數,名稱都是user。那么這兩個請求參數必須通過getParameterValues方法來獲取參數。此時user請求參數必須是數組類型,或者List類型(實際上,List和數組是完全相通的)。
24,因為struts2內建的OGNL表達式的支持,那么可以用另一種方式將請求參數轉換成復合類型,如(JSP頁面中):
 <input type=text name="user.name"/>,<input type=text name="user.pass"/>這樣就不需要轉換器了。
 通過這種方式也可以把字符串轉換成復合類型。但需要注意以下幾點:
 ①因為struts2是需要直接創(chuàng)建一個復合類(User類)的實例,因此系統(tǒng)必須為該復合類構建一個無參的構造方法。
 ②如果希望使用user.name請求參數的形式為Action實例的user屬性和pass屬性賦值,則必須為user屬性對應的復合類型提供setName方法,因為struts2是通過該方法類為屬性賦值的。當然Action類還應該包含setUser方法。
25,表單元素enctype屬性指定的是表單數據的編碼方式。屬性有如下3個值:
 ①application/x-www-form-urlencoded:這是默認的編碼方式。它只處理表單中的value屬性值,采用這種編碼方式會將表單域的值處理成URL編碼方式。
 ②multipart/form-data:這種編碼方式會以二進制流的方式來處理表單數據,這種編碼方式會把文件域指定的文件內容也封裝到請求參數里。
 ③text/plain:這種編碼方式當表單的action的屬性為mailto:URL的形式時比較方便,這種方式主要適用于直接通過表單發(fā)送郵件的方式。
26,通過Action在jsp頁面輸出提示信息,我們可以
 ①在Action中添加一個屬性(通過setXx方法設置屬性值),然后通過struts2的標簽(<s:properties value="xx"/>)在jsp頁面輸出。
 ②通過ActionContext類來處理,如:ActionContext.getContext.put(key,value);然后通過EL表達式進行輸出。
27,在Form表單中action屬性的值要得到【上下文路徑】:
 ①<%=request.getContextPath()%>
 ②還可以通過EL表達式得到 :${pageContext.request.contextPath}
28,得到【ValueStack】的對象有哪幾種方法:
 ①ServletActionContext類中的方法:static getValueStack(HttpServletRequest req)【Gets the current value stack for this request】;
 ②ActionContext類中的方法:getValueStack()【Gets the OGNL value stack.】;
 ③ValueStack vs = (ValueStack) request.getAttribute("struts.valueStack");
 (request.getAttribute()返回一Object類型)
29,【攔截器】。在默認的情況下,如果我們?yōu)槟硞€Action定義了攔截器,則這個攔截器會攔截Action的所有方法。可能在有些情況下,我們無需攔截器所有的方法,只需要攔截某些方法,此時就需要struts2攔截器的方法過濾特性。
30,struts2的【校驗】,可以繼承ActionSupport類重寫validate方法,利用ActionSupport的addFieldError方法把錯誤信息通過key保存起來,在jsp頁面通過struts2標簽的fielderror屬性輸出錯誤信息。注意:struts2的校驗在配置action的時候需要提供輸入頁面(就是<result name="input">)。這是對action中的所有方法進行校驗。
 如果要對action中指定的方法進行校驗,把validate方法名改為:validateXxx,其中Xxx是需要校驗的指定方法名。
31,輸入校驗的流程:
 ①類型轉換器把請求參數進行類型轉換,并把轉換后的值賦給action中的屬性。
 ②如果在執(zhí)行類型轉換的過程中出現異常,系統(tǒng)會將異常信息保存到ActionContext中,conversionError攔截器將異常信息 添加到fieldErrors中。不管類型轉換是否失敗都會轉入第三步。
 ③系統(tǒng)通過反射技術調用action中的validateXxx方法。
 ④再調用validate方法。
 ⑤如果fieldErrors中存在錯誤信息,系統(tǒng)自動將請求轉發(fā)至input視圖。如果沒有錯誤信息將執(zhí)行action中的方法。
 注意:如果validate方法里沒有問題,卻返回input頁面,可能是類型轉換有問題。所以返回input視圖有兩種原因(類型轉換有問題或校驗出錯).
32,基于xml配置方式對action內所有的方法進行校驗,xml文件的命名規(guī)則是:ActionClassName-validation.xml
 如果只需要對action內指定的方法進行校驗,則xml文件的命名規(guī)則為:ActionClassName-ActionName-validation.xml。其 中ActionName(action的邏輯名稱)。它的配置一般用通配符(有助于實驗)。
 ①基于xml配置方式的校驗,如果ActionClassName-validation.xml、ActionClassName-ActionName-validation.xml同時存在則把兩個文件匯總,在進行校驗。如果兩個xml文件的校驗規(guī)則起了沖突則執(zhí)行后面的xml文件。
 ②如果action繼承了另一個action則先找到父action校驗文件,在找到子action校驗文件,再把4(每個action都有指定方法名或非指定方法名)個文件匯總。
33,【國際化】。國際化按范圍分為:全局、action、package的范圍的資源文件。Properties文件命名的規(guī)則為:xxx_language_country.properties(xxx為用戶定義的名字,第二部分為語言類別。)
 Ⅰ定義好了國際化文件后,需要在struts.xml文件配置<constants name="struts.custom.i18n.resources" value="國際化文件的名稱(xxx)">[這是定義全局的國際化資源文件],可以在jsp頁面顯示國際化信息<s:text name="key"/>。
 Ⅱ也可以通過action類繼承ActionSupport類,再調用個getText方法的資源文件的key(getText("key")).然后可以通過EL表達式在jsp頁面輸出。
 Ⅲ也可以通過struts2的表單標簽的key屬性。如<s:textfield key="key"/>或<s:textarea key="key"/>
 輸出帶有占位符的國際化信息:
 ①<s:text name="key"><s:param>....</s:param>..</s:text>
 ②通過ActionSupport類的getText(String key,String[] str)或者getText(String key,List list)
34,包范圍的國際化資源文件,
 在大型的應用程序中,整個應用有大量的內容需要國際化,如果我們把國際化的內容放置在全局資源屬性文件中,顯然會導致資源文件變得過于龐大、臃腫,不便于維護,這個時候我們需要針對不同的模塊,使用包范圍來組織國際化文件。
 在java的包下創(chuàng)建名為:package_language_country.properties的資源文件,package為固定寫法,language_country是對應的語言類別。處于該包及子包都可以訪問該資源文件。當在包范圍找不到對應的資源文件,然后會在全局范圍內查找。
35,Action范圍的資源文件。在Action所在的路徑創(chuàng)建名為:ActionClassName_language_country.properties
 如果同時存在全局、package、Action范圍的國際化資源文件,系統(tǒng)搜索的順序是:Action-->package-->全局范圍。
36,以上三種配置有的是基于配置的國際化資源文件。我們也可以通過無配置的方式進行直接訪問某個資源文件。
 通過struts2標簽,如:
 <s:i18n name="xxx">
 <s:text name="key">
 </s:i18n> 其中xxx是全局范圍文件的名稱的前綴。
 如果直接想訪問包范圍的國際化資源文件
 <s:i18n name="com.johnny.action.package">
 <s:text name="key">
 </s:i18n> 其中package是固定寫法。
?
37,OGNL表達式(Object Graphic Navigation Language對象圖導航語言),當struts2接受一個請求時,會迅速創(chuàng)建ActionContext、ValueStack、action,然后把action存放在ValueStack,所以OGNL表達式可以迅速訪問action實例的屬性。
 OGNL表達式一般要配合Struts2標簽使用。
 在struts2中,EL表達式只能訪問OgnlValueStack的root里的屬性。即action的屬性(因為action的屬性放在OgnlValueStack的root屬性里)。利用OGNL表達式創(chuàng)建List/Map對象,<s:set var="" value="" scope=""/>scope指定變量的被放置的范圍,可以為application、session、request、page和action。如果沒有設置屬性,則默認為OGNLContext(OGNL上下文)中,如果在OGNLContext訪問時不用#,如果scope為request....中,則需要用#。value:賦給變量的值,如果沒有該屬性,則將ValueStack的棧頂的值賦給變量。
38,防止表單重復提交,首先要有struts的token標簽。再使用系統(tǒng)的攔截器。
?
總結
以上是生活随笔為你收集整理的Struts2技术详解的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Struts2中OGNL,valueSt
- 下一篇: struts2 处理请求流程分析(结合源
