1.全局的邏輯控制器為一個(gè)過濾器,負(fù)責(zé)過濾所有的請求。該過濾器引用的API類為
org.apache.struts2.disapatcher.FilterDispatcher
2.MVC:頁面請求(jsp)——>邏輯控制器(Filter)——>業(yè)務(wù)控制器(Action)——>業(yè)務(wù)邏輯組件——>業(yè)務(wù)處理/DAO
3.struts2的配置文件放在classpath下。
4.struts2的類型轉(zhuǎn)換:
a.繼承DefaultTypeConverter,
覆蓋父類的public Object convertValue(Map context, Object value, Class toType)方法
b.繼承StrutsTypeConverter,
覆蓋父類的public Object convertFromString(Map context, String[] values, Class toClass)
該方法負(fù)責(zé)轉(zhuǎn)換從頁面?zhèn)鬟f過來的數(shù)據(jù)。
覆蓋父類的public String convertToString(Map context, Object o)
該方法負(fù)責(zé)將Action中處理好的數(shù)據(jù)轉(zhuǎn)換成相應(yīng)格式的字符串。
5.struts2的數(shù)據(jù)驗(yàn)證:
a.使用編碼方式進(jìn)行驗(yàn)證。業(yè)務(wù)控制器Action繼承ActionSupport類,重寫public void validate()方法。
在該方法中進(jìn)行數(shù)據(jù)驗(yàn)證。若Action中處理業(yè)務(wù)的方法為test,則可以編寫public void validateTest()
方法,來對test方法的數(shù)據(jù)進(jìn)行驗(yàn)證。(系統(tǒng)在進(jìn)行validateTest方法后,會(huì)接著執(zhí)行validate方法,然后
才執(zhí)行相應(yīng)的業(yè)務(wù)代碼。)
若嚴(yán)重出錯(cuò),則可以調(diào)用addFieldError或者調(diào)用addActionError方法,增加相應(yīng)的錯(cuò)誤提示信息。
b.使用配置xml文件進(jìn)行驗(yàn)證。驗(yàn)證文件的名字為:×××Action-validation.xml。驗(yàn)證的方式包含字段驗(yàn)證和非字段驗(yàn)證。
其中字段驗(yàn)證表示對某個(gè)字段進(jìn)行某些類型的驗(yàn)證。非字段驗(yàn)證表示用某個(gè)類型的驗(yàn)證來驗(yàn)證,某個(gè)字段。兩種方式
底層實(shí)現(xiàn)一樣,只是表現(xiàn)方式不同,字段驗(yàn)證方式比較直觀。
驗(yàn)證的類型有一下幾種:required,requiredstring,int,date,double,expression,fieldexpression
email,url,visitor,conversion,stringLength,regex(正則表達(dá)式)。
對驗(yàn)證類型可以指定shourt-circuit參數(shù)為true,來執(zhí)行短路驗(yàn)證。
如果Action中執(zhí)行業(yè)務(wù)的方法為test,則可以通過編寫×××Action-test-validation.xml方法來對test方法的數(shù)據(jù)進(jìn)行
驗(yàn)證。且執(zhí)行完test方法的私有驗(yàn)證文件后,還會(huì)執(zhí)行默認(rèn)的驗(yàn)證文件×××Action-test-validation.xml的驗(yàn)證。
c.struts2進(jìn)行客戶端的驗(yàn)證。首先需要使用struts2的標(biāo)簽庫,且標(biāo)簽庫的theme屬性不能為simple,然后設(shè)置標(biāo)簽的
validate屬性為true。
注意:struts2的客戶端驗(yàn)證依賴于服務(wù)器的驗(yàn)證配置文件。
6.struts2的攔截器。struts2的攔截器是struts2的核心,其底層實(shí)現(xiàn)使用了Java的反射機(jī)制與動(dòng)態(tài)代理。在struts2的配置文件中
為一個(gè)Action引入了一個(gè)攔截器,則配置的默認(rèn)攔截器不會(huì)被調(diào)用,需要手工配置到該Action中。
實(shí)現(xiàn)struts2攔截器的方法:
a.實(shí)現(xiàn)Interceptor接口,并實(shí)現(xiàn)init,destrory以及intercept方法。
b.繼承AbstractInterceptor類,覆蓋intercept方法。
c.繼承MethodFilterInterceptor類,覆蓋intercept方法。該類可以對特定的方法進(jìn)行攔截。
攔截器??梢园瑪r截器和攔截器棧。
7.文件的上傳和下載:
a.使用apache組織開發(fā)的commons-fileupload和commons-io包,并且按需要配置fileUpload攔截器和相應(yīng)的上傳參數(shù),
比如上傳文件的類型,上傳文件的大小。多文件的上傳可以使用js代碼來在頁面修改上傳文件的列表,在Action中
則用三個(gè)列表分別來保存文件對象(file),文件名(fileName),以及文件類型(fileContentType)。
b.文件下載使用流進(jìn)行讀?。簉eturn ServletActionContext.getServletContext.getResourceAsStream("文件名")
并將Action的結(jié)果返回類設(shè)定為stream,即流。按需要配置相應(yīng)的參數(shù)。
8.struts2的國際化。struts2國際化的底層實(shí)現(xiàn)用到了Java基礎(chǔ)類庫中的Locale(地區(qū))和ResourceBundle(消息資源)兩個(gè)類。
struts2的國際化主要用在一下幾個(gè)地方:
a.jsp頁面:使用struts2的標(biāo)簽時(shí),指定標(biāo)簽的key屬性(對應(yīng)消息資源文件中的key)。
使用<s:text name="key">
<s:param></s:param>
</s:text>
標(biāo)簽取得消息資源信息。
還可以用<s:i18n name="basename"></s:i18n>標(biāo)簽來指定特定的消息資源文件。
b.Action中:調(diào)用getText(key)或者getText(key,args)方法取得消息資源文件中的消息資源。
c.xml驗(yàn)證文件中:指定message元素的key屬性(對應(yīng)消息資源文件中的key)。(怎么傳參數(shù)?)
d.類型轉(zhuǎn)換過程中:通過查看xwork包的源代碼可以找到:ge.properties文件中可以找到如下的鍵值對:
xwork.default.invalid.fieldvalue=Invalid field value for field "{0}".
在消息資源文件中重新指定該鍵值對即可。
另外在struts.properties中設(shè)定鍵值對struts.i18n.encoding=GBK,可以解決中文亂碼問題。
9.struts2的異常處理。在Action中,我們的業(yè)務(wù)邏輯處理方法都對拋出異常進(jìn)行了聲明。具體的異常對應(yīng)具體的處理結(jié)果。
在action配置中:
<action name="upload" class="uploadAction">
<result name="exception"></result>
<exception-mapping result="exception" exception="具體的異常類型"></exception-mapping>
</action>
還可以配置全局的異常處理:
<global-exception-mappings>
<exception-mapping result="" exception=""></exception-mapping>
</global-exception-mappings>
struts2的其他東西:
1.對于struts.xml中的package:
a.設(shè)置<package abstract="true">,則表明該包中沒有action的配置,只定義一個(gè)基礎(chǔ)公共的組件。
b.package的namespace可以將不同的請求路徑分隔開,在多人合作項(xiàng)目中用到比較多。當(dāng)接收到一個(gè)請求,
若在當(dāng)前的namespace中沒有相應(yīng)的請求地址,則會(huì)到默認(rèn)的namespace中去尋找匹配的地址。
2.模型驅(qū)動(dòng)機(jī)制(ModelDriven),將一個(gè)Action中的各個(gè)參數(shù)封裝成為一個(gè)JavaBean(類似struts1.x中的
ActionForm)。需要實(shí)現(xiàn)ModelDriven<T>接口,并實(shí)現(xiàn)getModel方法。當(dāng)一個(gè)Action實(shí)現(xiàn)ModenDriven接口后,
該Action會(huì)被ModenDrivenInterceptor攔截,進(jìn)行相應(yīng)的參數(shù)設(shè)置。
3.防止表單的重復(fù)提交:在jsp的表單中設(shè)置<s:token name="***"></s:token>標(biāo)簽。并且在相應(yīng)的Action
中設(shè)置token攔截器和名為invalid.token的返回結(jié)果。相應(yīng)出錯(cuò)信息的key為struts.message.invalid.token。
配置該key,來實(shí)現(xiàn)國際化。
4.struts2中Action與Servlet容器的耦合。主要有三種方式:
a.實(shí)現(xiàn)ServletRequestAware或ServletResponseAware接口。并提供對request或者response熟悉的設(shè)置方法。
b.使用ActionContext(但不能獲得response對象)。改方法方便單元測試。
c.使用ServletActionContext。ServletActionContext是ActionContext的子類。
首選使用ActionContext,其次ServletActionContext。
5.整合多個(gè)struts配置文件,在struts2的配置文件中使用include元素包含其他的配置文件。用于多模塊開發(fā)。
6.可以在web.xml中對struts2的核心過濾器FilterDispatcher設(shè)置初始化參數(shù)(不推薦使用)。
7.動(dòng)態(tài)方法調(diào)用(DynamicMethodInvocation).
a.action配置中指定:<action name="×××" method="">
b.在客戶端即頁面指定:<s:form action="method!actionName">
c.使用通配符:<action name="*Login" class="com.action.LoginAction" method="{1}">,
若Action的url為helloLogin,則調(diào)用LoginAction的hello來處理業(yè)務(wù)。此種方法簡化了配置,但是
使得程序不明了,不提倡使用該方法。
8.struts2的結(jié)果類型。在struts2-core包中,有幾種struts2已經(jīng)配置好的結(jié)果類型。
其中默認(rèn)的類型為dispatcher,此外還有:redirectAction,chain,freemaker,httpheader,redirect,
redirectAction,stream,velocity,xslt,plainText。
9.struts2與spring的整合。導(dǎo)入struts2-spring-plugin包,在web.xml中設(shè)置spring的監(jiān)聽器,
spring監(jiān)聽器對應(yīng)的API類為:org.springframework.web.context.ContextLoaderListener。
struts2-spring-plugin包為我們將struts2的對象工廠設(shè)置為spring的IoC容器,其代碼為:
<struts>
<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<!-- Make the Spring object factory the automatic default -->
<constant name="struts.objectFactory" value="spring" />
<package name="spring-default">
<interceptors>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
</interceptors>
</package>
</struts>
很明顯,將struts.objectFactory定位為org.apache.struts2.spring.StrutsSpringObjectFactory
其余的工作就交給spring的IoC容器去做了。
另外:當(dāng)我們需要增加spring的配置文件時(shí),需要在web.xml中設(shè)定contextConfigLocation參數(shù)。代碼如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>其他的spring配置文件名,用逗號隔開</param-value>
</context-param>
需要注意的一些地方
1.存儲(chǔ)fieldError的是一個(gè)LinkedHashMap<String,ArrayList>;而actionError則存儲(chǔ)在一個(gè)ArrayList中。
ActionSupport中的getFieldError方法返回的是一個(gè)新的集合。該集合是原fieldError集合的一個(gè)副本。
在struts2的源代碼中返回的是:new LinkedHashMap(internalGetFieldError),即一個(gè)新的集合對象。
所以執(zhí)行代碼:this.getFieldErrors.put("username","ErrorMsg");不會(huì)影響原fieldError集合的數(shù)據(jù)。
2.若一個(gè)Action注冊了PreResultListner,則會(huì)在該Action返回的時(shí)候調(diào)用相應(yīng)結(jié)果驗(yàn)證的邏輯代碼。
3.struts2-core包中的default.properties和struts-default.xml文件保存了一些struts2默認(rèn)的配置。
可以在自己的struts配置文件中對相應(yīng)的配置進(jìn)行覆蓋或重新設(shè)值。比如修改請求的后綴名:在struts.properties
中加入:
struts.action.extension = do
則將struts2請求的后綴名修改成了struts1中的do后綴名的形式。
4.在配置文件中配置struts.multipart.saveDir來設(shè)定上傳文件時(shí)的臨時(shí)文件的存儲(chǔ)位置。需要定期清理該路徑下的文件。