這周花了一個(gè)星期的時(shí)間學(xué)習(xí)了Struts2,今天就總結(jié)一下,以便后面使用時(shí)可以參考,順便理理思路,嘿嘿。
Struts和Struts2都是屬于控制轉(zhuǎn)發(fā)的框架,而在Struts2中功能比較強(qiáng)大,而且使用方便,不過(guò)我在好多測(cè)試中都很費(fèi)神,因?yàn)椴粓?bào)錯(cuò),也不出來(lái)我想要的結(jié)果,很無(wú)奈,嘿嘿!
首先說(shuō)下它的應(yīng)用如何搭建:在老版本中有5個(gè)必須包,但是現(xiàn)在我用的是2.1.8這個(gè)版本就不止5個(gè)jar包了,
包括:
struts2-core-2.1.8.jar(這是struts2的核心包),commons-loging-1.0.4.jar(通用日志記錄包),
freemarker-2.3.15.jar(是一個(gè)模板引擎,一個(gè)基于模板生成文本輸出的通用工具),
ognl-2.7.3.jar(這是struts2的表達(dá)式語(yǔ)言庫(kù)即對(duì)象圖導(dǎo)航語(yǔ)言),
xwork-core-2.1.6.jar(由于struts2就是從xwork衍生過(guò)來(lái)的,所以這包夜是必須的), commons-fileupload-1.2.1.jar(struts2的上傳下載包),
common-io-1.3.2.jar(這個(gè)包在低版本中是不需要的),
struts-convention-plugin-2.1.8.jar(這是注解配置用的),我在這列出了這8個(gè)jar包基本是就夠用了。
導(dǎo)入包后如果不用注解配置,那struts2也肯定有個(gè)配置文件,默認(rèn)叫struts.xml,這個(gè)文件必須放在classes中,也就是放在src下。
這兩件事做完后就要在web.xml中進(jìn)行配置,因?yàn)閟truts2跟1不一樣,它不用配置servlet,而是過(guò)濾器,配置如下(固定寫法):
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<!-- 這個(gè)參數(shù)是注解用的 -->
<init-param>
<param-name>actionPackages</param-name>
<param-value>com.mwt.action.zhujie</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
以上步驟做完之后,struts2的架子也就搭起來(lái)了,好像不是很復(fù)雜哦!
接下來(lái)我主要說(shuō)下struts2的運(yùn)行流程和它的重點(diǎn)也就是常用的功能:
當(dāng)我們?cè)陧?yè)面發(fā)出一個(gè)請(qǐng)求之后,由于服務(wù)器提前已經(jīng)加載了web.xml,所以這個(gè)過(guò)濾器就會(huì)攔截到所有的請(qǐng)求,然后會(huì)默認(rèn)去classes下的
struts.xml中找對(duì)應(yīng)的action(即action配置標(biāo)簽中的name屬性),在struts2中訪問(wèn)后綴是.action,不寫后綴也會(huì)被
默認(rèn)加上.action。action執(zhí)行完后都會(huì)返回一個(gè)字符串,此時(shí)在去struts.xml中找result標(biāo)簽的name屬性對(duì)應(yīng)的資源,可以是
jsp、html、.action等。
舉例說(shuō)明:
1、action
struts2中的action很簡(jiǎn)單,不用集成任何類,也不用實(shí)現(xiàn)任何接口,這和struts1是有區(qū)別的,他只要有一個(gè)返回字符串的execute方法就行了,但如果有多個(gè)方法時(shí),名字也可以隨便起,不一定是execute。
2、struts.xml
這個(gè)配置文件是struts2的核心配置文件,這個(gè)沒(méi)什么可說(shuō)的,就直接貼出代碼再代碼中詳細(xì)的介紹吧:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<!-- struts2的默認(rèn)過(guò)濾編碼是utf-8,所以我們也就不用去寫過(guò)濾器來(lái)轉(zhuǎn)碼了,但是如果想改的話也可以 -->
<!-- struts2的配置文件要放在classes下,所以在項(xiàng)目中也就是放在src中了 -->
<struts>
<!-- 當(dāng)一個(gè)項(xiàng)目中action非常多是我們就可以分開好多個(gè)xml配置文件然后用include去引入它們 -->
<include file="struts1.xml"></include>
<!-- 這個(gè)struts-default必須繼承,它會(huì)默認(rèn)加上好多攔截器,如果不繼承它的話就連result等好多標(biāo)簽都無(wú)法使用 -->
<package name="bao" extends="struts-default">
<!-- 沒(méi)有配置命名空間namespace,如果頁(yè)面發(fā)出任何請(qǐng)求的話,那么struts會(huì)在這里的找所有的action中與name對(duì)應(yīng)的action類,name是要訪問(wèn)的action起的名字,class對(duì)應(yīng)的全類名 -->
<action name="login" class="com.mwt.action.LoginAction">
<result name="success">/success.jsp</result>
<!--
在result中有個(gè)type屬性就是專門配置是否為客戶端跳轉(zhuǎn),默認(rèn)是服務(wù)器端跳轉(zhuǎn),若加上redirect后瀏覽器地址欄會(huì)從客戶端從新訪問(wèn)即就不會(huì)
傳遞參數(shù)給頁(yè)面了,就和Servlet中的sentRedirect一樣 -->
<result name="error" type="redirect">/fail.jsp</result>
</action>
<action name="getRequest" class="com.mwt.action.GetRequestTest">
<!-- 跳到命名空間為global下的a2這個(gè)action -->
<result name="success" type="chain">/global/a2</result>
</action>
</package>
<!-- 在這說(shuō)說(shuō)package中的name屬性,到現(xiàn)在為止我是沒(méi)有感覺(jué)到它的意義, 但是我的一個(gè)朋友(秉承)說(shuō)是當(dāng)extends繼承包時(shí)就是參考的這個(gè)name屬性,看來(lái)這點(diǎn)是被我忽略了。-->
<package name="test2" extends="struts-default" namespace="/test2">
<action name="m" class="com.mwt.action.Method">
<!-- 這里調(diào)用不同的方法,在頁(yè)面用感嘆號(hào)動(dòng)態(tài)調(diào)用,下面在用method做測(cè)試 -->
<result name="add">/methodTest/add.jsp</result>
<result name="update">/methodTest/update.jsp</result>
<result name="delete">/methodTest/delete.jsp</result>
</action>
</package>
<package name="test1" extends="struts-default" namespace="/test1">
<!-- 這里調(diào)用不同的方法用method做測(cè)試,缺點(diǎn)是同一個(gè)action中的不同方法調(diào)用要配置好多action,優(yōu)點(diǎn)可以加不同的攔截器 -->
<action name="add" class="com.mwt.action.Method" method="add">
<result name="add">/methodTest/add.jsp</result>
</action>
<action name="update" class="com.mwt.action.Method" method="update">
<result name="update">/methodTest/update.jsp</result>
</action>
</package>
<!-- 通配符 (使用通配符時(shí)struts2會(huì)按照你在xml文件中配置的順序去一一匹配),這樣就可以只寫一個(gè)action,只要方法和頁(yè)面名字有規(guī)律就可以自動(dòng)調(diào)用所有的方法和頁(yè)面-->
<package name="User" extends="struts-default" namespace="/user">
<action name="*User" class="com.mwt.action.UserAction" method="{1}User">
<result name="success">{1}User.jsp</result>
</action>
</package>
<!-- action之間的跳轉(zhuǎn) -->
<package name="aciton1" extends="struts-default" namespace="/action1">
<action name="a1" class="com.mwt.action.A1">
<!-- 這個(gè)type="chai"指的是服務(wù)器端action的跳轉(zhuǎn),如果在不同的命名空間下就在a2前面加上另一個(gè)action的命名空間就行了,這里的param屬性也可以不加 -->
<result name="success" type="chain">
<param name="actionName">a2</param>
</result>
<!-- <result name="success" type="chain">a2</result>也可以這么寫 -->
</action>
<action name="a2" class="com.mwt.action.A2">
<!-- 在struts2中的配置文件中也可以用${}表達(dá)式,這個(gè)表達(dá)式很想EL表達(dá)式,但其實(shí)這是struts2自帶的OGNL表達(dá)式(對(duì)象圖導(dǎo)航語(yǔ)言),它會(huì)把前面action中的有g(shù)et\set方法的屬性值自動(dòng)取出來(lái) -->
<result name="success" type="redirect">/success.jsp?username=${username}</result>
</action>
</package>
<!-- 全局結(jié)果集,在下面的包中所有的action都會(huì)跳到同一個(gè)頁(yè)面 -->
<package name="global" extends="struts-default" namespace="/global">
<global-results>
<result name="success">/success.jsp</result>
<result name="error">/fail.jsp</result>
</global-results>
<action name="a1" class="com.mwt.action.A1"/>
<action name="a2" class="com.mwt.action.A2"/>
</package>
<!--
action之間傳遞值(這個(gè)服務(wù)器端的傳遞會(huì)把第一個(gè)action中同名的屬性值直接賦給第二個(gè)action中,他兩都共用了同一個(gè)值棧,而且后放進(jìn)去
的(s2)先取出來(lái)。),如果是客戶端跳轉(zhuǎn)頁(yè)可以用***.action?username=${name}&
passward=${pwd}這中方式進(jìn)行傳值-->
<package name="student" extends="struts-default">
<action name="s1" class="com.mwt.action.Student1">
<result name="success" type="chain">s2</result>
</action>
<!--
自定義攔截器只要實(shí)現(xiàn)接口,或者繼承一個(gè)類,這都是struts2自帶的,如下配置。
<interceptors>
<interceptor name="a" class="b"></interceptor>
</interceptors>
-->
<action name="s2" class="com.mwt.action.Student2">
<result name="success">/success.jsp</result>
<!--在這里引用下上面配置的攔截器就行了(切記還要引用下默認(rèn)的攔截器,否則struts2的好多功能就無(wú)效了,這就好比Java中的構(gòu)造器一
樣。) <interceptor-ref name="a"></interceptor-ref> -->
</action>
</package>
</struts>
3、在看看action,這個(gè)action很簡(jiǎn)單就一個(gè)方法。
public class LoginAction extends ActionSupport{
User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String execute(){
if(user.getUsername().trim().equalsIgnoreCase("baobao"))
return SUCCESS;
//因?yàn)槔^承了ActionSupport,所以可以直接這樣返回,其實(shí)內(nèi)部也是返回了一個(gè)小寫的success字符串。
return ERROR;
}
}
4、在看看頁(yè)面的訪問(wèn)方式:
<a href="<%=path%>/test2/m!add.action">add</a> 訪問(wèn)命名空間為test2下的name值為m的這個(gè)action種方法名叫add()的方法。
<a href="s1.action">s1</a><hr>
<a href="s1">s1</a><hr>這兩中寫法是一樣的。
5、頁(yè)面獲取值方式:
<!--struts2的核心技術(shù)就是ValueStack值棧技術(shù)!
默認(rèn)所有的action都會(huì)放在值棧中,一個(gè)請(qǐng)求就會(huì)產(chǎn)生一個(gè)值棧。棧是先進(jìn)后出,如果是服務(wù)器之間action跳轉(zhuǎn)(a1->a2的跳轉(zhuǎn)再到頁(yè)
面),那么這兩個(gè)action共用同一個(gè)值棧,而在前臺(tái)取出的值是先從a2中找,然后從a1中找,棧是后來(lái)的在棧頂。值棧中的值不會(huì)在action中相互
傳遞,同名屬性值也不會(huì)被覆蓋,都是遵循后進(jìn)先出的形式去獲取內(nèi)容。 -->
<h1>歡迎您:<s:property value="user.username"/></h1>
<p>用戶名:${param.username}</p><hr>
<p>Request作用域測(cè)試:username=${username}</p>
<!-- 在action中有g(shù)et和set方法的屬性在這里用值棧技術(shù)都能直接取出來(lái) -->
<p>s=${s}</p><hr>
<!-- OGNL表達(dá)式測(cè)試(對(duì)象導(dǎo)航圖語(yǔ)言) -->
ognl獲得的用戶名稱:<s:property value="user.username"/><br>
用el也可以代替上面的struts2標(biāo)簽(說(shuō)明struts2的值棧中的內(nèi)容也放進(jìn)了request作用域!):${user.username}<br>
<p><%=request.getAttribute("user.username")%></p><!-- 這里就證明了值棧中的值確實(shí)放到了request作用域中 -->
<!-- 在這里調(diào)用方法傳遞參數(shù)的時(shí)候,用單引號(hào),像這樣調(diào)用方法就可以替代自定義函數(shù)標(biāo)簽庫(kù)了 -->
調(diào)用user對(duì)象中的公共方法(屬于值棧中):<s:property value="user.f('ma','wentao')"/><br>
<!-- 如果調(diào)用action中或者JDK的靜態(tài)方法就直接寫全類名(試驗(yàn)未成功,很納悶) -->
調(diào)用JDK中靜態(tài)方法(返回個(gè)0到1的隨機(jī)數(shù)):<s:property value="@java.lang.Math@random()"/><br>
如果是java.lang.Math下的類可以省略掉前面的類:<s:property value="@@random()"/><hr>
<!-- 很納悶,測(cè)試失敗,這個(gè)f()方法一直沒(méi)有被執(zhí)行。 -->
action中靜態(tài)方法調(diào)用:<s:property value="@vs@f()"/><!-- 這里的vs就代表valuestack值棧,屬于固定寫法。 -->
6、在action中如何獲得HttpServletRequest對(duì)象,有了它HttpSession也就很容易獲得了。
/*
* 第一種方式:用ServletActionContext這個(gè)類的getRequest()靜態(tài)方法就可以直接獲取request,但必須在方法中 * 初始化,不能直接給類成員賦值。
* 第二種方式:用IOC控制反轉(zhuǎn)直接注入request,這是struts2自帶的注入,只要實(shí)現(xiàn)了ServletRequestAware這個(gè)借 * 口再實(shí)現(xiàn)了它的set方法就行了
* 今天就用第二種方式做個(gè)試驗(yàn)
* 注意:其實(shí)在用struts2時(shí)很少用到request這個(gè)對(duì)象,因?yàn)樵赼ction中所有的屬性都會(huì)通過(guò)struts2的值棧技術(shù)直接 * 傳到頁(yè)面或者另一個(gè)action。
*
*/
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
//不用request,就用${}再頁(yè)面直接取值,這種值棧技術(shù)很難讓人琢磨
//s或者其他域只要有g(shù)et和set方法就能在令一個(gè)action或者頁(yè)面直接取值。
private String s;
private double d;
public String execute(){
request.setAttribute("username","感冒快點(diǎn)好吧!");
s="值棧技術(shù)存值";//在頁(yè)面直接用${s}取值
d=1232354;//在另一個(gè)action中取值
return SUCCESS;
}
7、最后在說(shuō)下struts2的注解,注解的好處顯而易見,它可以讓框架完全脫離xml配置文件,很容易學(xué)習(xí),配置起來(lái)也相當(dāng)方便,我還是挺喜歡這種配置
的,其實(shí)好多框架都用到了注解,比如hibernate、spring都有注解,這些就跟JDK中的注解一樣,比如@Override這個(gè)就是重寫提示的
注解。
我用struts2就做了一個(gè)小例子,可結(jié)果很令人失望,一直不出效果,難道與版本有關(guān)系?哎,還是先貼出代碼吧!
/*
* struts2注解(先看action注解,這個(gè)struts2真的很奇怪,老版本跟新版本的注解變化很多)
* 老版本直接用,而且注解標(biāo)示也不多,action也就4個(gè),而這新版本我用的是struts2.1.8還要再導(dǎo)個(gè)包
* 叫struts2-convention-plugin-2.1.8.jar幸好這包在源碼包中有。
*/
//首先標(biāo)注必須在web.xml中配置注冊(cè)下
//@ParentPackage(value="struts-default")默認(rèn)就這包可以不寫
//@Namespace(value="space")可以不要命名空間
//@Result(name="success",location="/success.jsp")這里只有一個(gè)跳轉(zhuǎn)結(jié)果時(shí)用,在老版本這個(gè)location要換成value
@Namespace(value="space")
@Action(value="test",results={
@Result(name="success",location="/success.jsp"),
@Result(name="error",location="/fail.jsp",type="redirect")
})
public class ZhujieAction extends ActionSupport{
//這里的名字可必須以Action為后綴,訪問(wèn)時(shí)就以前面的單詞首字母改成小寫就行了。(不過(guò)有多個(gè)方法怎么分辨還不清楚,可能會(huì)在@Action()中配置多個(gè)value屬性。)
public String test(){
if(1>0) return SUCCESS;
else return ERROR;
}
}//現(xiàn)在還是測(cè)試不成功,算了,先放棄吧!代碼絕對(duì)沒(méi)問(wèn)題(多么自信的男人呀,嘿嘿!)。
好了,Struts2就先寫到這,這些都是比較常用的知識(shí)點(diǎn),其實(shí)struts2還有好多功能呢,比如自帶了好多攔截器跟過(guò)濾器作用差不多,不過(guò)功能比較
強(qiáng)大,還有它的好多標(biāo)簽在頁(yè)面我也很少用,我從來(lái)不專門學(xué)習(xí)一個(gè)框架的標(biāo)簽的,感覺(jué)很浪費(fèi)時(shí)間,而且意義不大,struts2還有自己的文件上傳下載、異
常處理、OGNL導(dǎo)航表達(dá)式等等,這些就等用到了再學(xué)吧。好了就先說(shuō)到這吧,今天上班來(lái)的早,公司就我一個(gè)人,太安靜了,所以突然說(shuō)了這么多,嘿嘿!
補(bǔ)充:
★Struts中的OGNL(對(duì)象圖導(dǎo)航語(yǔ)言)采用了struts2的標(biāo)簽獲取值,因此我很少用,上面也說(shuō)過(guò)不喜歡用某種框架自帶的標(biāo)簽,但見了要能認(rèn)
識(shí)。比如:Struts2中的HttpSession已經(jīng)被封裝成了Map類型,只要類實(shí)現(xiàn)了SessionAware這接口,重寫了
setSession就可以自動(dòng)注入進(jìn)去,在頁(yè)面用的話就直接 <s:property
value="#session.userName"/>,這只是#的其中一種用法,其實(shí)它也就等價(jià)于
session.getAttribute("userName");不過(guò)我還是習(xí)慣用HttpSession。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。