- Apache Struts 2是一種流行的 Java模型 - 視圖 - 控制器(MVC)框架,成功地結(jié)合了 WebWork和Struts1.x 兩種 web 框架。
struts2與struts1區(qū)別 (經(jīng)常聽(tīng)搞java的同事嗶嗶這個(gè)面試題)
- Struts 2是Struts的下一代產(chǎn)品,是在 struts 1和WebWork的技術(shù)基礎(chǔ)上進(jìn)行了合并的全新的Struts 2框架。其全新的Struts 2的體系結(jié)構(gòu)與Struts 1的體系結(jié)構(gòu)差別巨大。Struts 2以WebWork為核心,采用攔截器的機(jī)制來(lái)處理用戶的請(qǐng)求,這樣的設(shè)計(jì)也使得業(yè)務(wù)邏輯控制器能夠與ServletAPI完全脫離開(kāi),所以Struts 2可以理解為WebWork的更新產(chǎn)品。雖然從Struts 1到Struts 2有著太大的變化,但是相對(duì)于WebWork,Struts 2的變化很小。從某種程度上來(lái)看,Struts 2是WebWork的升級(jí),而不是Struts 1的升級(jí),甚至在Apache的Struts 2的官方文檔都提到:WebWork到Struts 2是一次平滑的過(guò)渡。實(shí)際上,Struts 2.0其實(shí)是WebWork 2.3而已。在很多方面,Struts 2僅僅是改變了WebWork下的名稱,Struts 2也刪除了WebWork中少量特性。
-
Struts實(shí)現(xiàn)MVC的原理
Struts實(shí)現(xiàn)MVC的原理 - 控制:通過(guò)圖可以看到有一個(gè)XML文件Struts-config.xml,與之相關(guān)聯(lián)的是Controller,它可以稱作為Struts神經(jīng)中樞。承擔(dān)MVC中Controller角色的是一個(gè)Servlet,叫ActionServlet。ActionServlet是一個(gè)通用的控制組件。這個(gè)控制組件提供了處理所有發(fā)送到Struts的HTTP請(qǐng)求的入口點(diǎn)。它截取和分發(fā)這些請(qǐng)求到相應(yīng)的動(dòng)作類(這些動(dòng)作類都是Action類的子類)。另外控制組件也負(fù)責(zé)用相應(yīng)的請(qǐng)求參數(shù)填充 Action From(通常稱之為FromBean),并傳給動(dòng)作類(通常稱之為ActionBean)。
- 流程:在Struts中,用戶的請(qǐng)求一般以.do作為請(qǐng)求服務(wù)名,所有的.do請(qǐng)求均被指向ActionSevlet,ActionSevlet根據(jù)Struts-config.xml中的配置信息,將用戶請(qǐng)求封裝成一個(gè)指定名稱的FormBean,并將此FormBean傳至指定名稱的ActionBean,由ActionBean完成相應(yīng)的業(yè)務(wù)操作,如文件操作,數(shù)據(jù)庫(kù)操作等。每一個(gè)*.do均有對(duì)應(yīng)的FormBean名稱和ActionBean名稱,這些在Struts-config.xml中配置。動(dòng)作類實(shí)現(xiàn)核心商業(yè)邏輯,它可以訪問(wèn)java bean 或調(diào)用EJB。最后動(dòng)作類把控制權(quán)傳給后續(xù)的JSP 文件,后者生成視圖。所有這些控制邏輯利用Struts-config.xml文件來(lái)配置。表現(xiàn)邏輯和程序邏輯。
- 視圖:主要由JSP生成頁(yè)面完成視圖。
- 模型:模型以一個(gè)或多個(gè)java bean的形式存在。這些bean分為三類:Action Form、Action、JavaBean or EJB。Action Form通常稱之為FormBean,封裝了來(lái)自于Client的用戶請(qǐng)求信息,如表單信息。Action通常稱之為ActionBean,獲取從ActionSevlet傳來(lái)的FormBean,取出FormBean中的相關(guān)信息,并做出相關(guān)的處理,一般是調(diào)用Java Bean或EJB等。
-
核心:Struts的核心是ActionSevlet,ActionSevlet的核心是Struts-config.xml。
20130904161742156.jpg - 客戶端(Client)向Action發(fā)用一個(gè)請(qǐng)求(Request)
- Container通過(guò)web.xml映射請(qǐng)求,并獲得控制器(Controller)的名字
- 容器(Container)調(diào)用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前調(diào)用FilterDispatcher,Struts2.1以后調(diào)用StrutsPrepareAndExecuteFilter
- 控制器(Controller)通過(guò)ActionMapper獲得Action的信息
- 控制器(Controller)調(diào)用ActionProxy
- ActionProxy讀取struts.xml文件獲取action和interceptor stack的信息。
- ActionProxy把request請(qǐng)求傳遞給ActionInvocation
- ActionInvocation依次調(diào)用action和interceptor
- 根據(jù)action的配置信息,產(chǎn)生result
- Result信息返回給ActionInvocation
- 產(chǎn)生一個(gè)HttpServletResponse響應(yīng)
- 產(chǎn)生的響應(yīng)行為發(fā)送給客服端。
Struts 2 各種文件詳解:
- Struts 2 體系結(jié)構(gòu) :
1、Web瀏覽器請(qǐng)求一個(gè)資源。
2、過(guò)濾器Dispatcher查找方法,確定適當(dāng)?shù)腁ction。
3、攔截器自動(dòng)對(duì)請(qǐng)求應(yīng)用通用功能,如驗(yàn)證和文件上傳操作。
4、Action的execute方法通常用來(lái)存儲(chǔ)和重新獲得信息。
5、結(jié)果被返回到瀏覽器。 - 開(kāi)發(fā)Struts 2 最少用到的jar文件:
- Struts-core-2.x.x.jar : Struts 2 框架的核心類庫(kù)
- xwork-2.x.x.jar : XWork類庫(kù),Struts 2 在其上構(gòu)建,由于struts2很多事基于webwork的,因此也需要這個(gè)的核心包
- ognl-2.6.x.jar : Object Graph Navigation Language ,Struts 2 框架通過(guò)其讀寫對(duì)象的屬性,提供了OGNL表達(dá)式。
- freemarker-2.3.x.jar : Struts 2 的UI標(biāo)簽的模版使用 Freemarker編寫,提供了另一種展現(xiàn)方式。
- commons-logging-1.1.x.jar : ASF出品的日志包,apache commons的jar包。
- commons-fileupload-1.2.1.jar : 文件上傳組件,apache commons的jar包。
- struts.xml文件
- Struts.xml是 Struts 2 的核心配置文件,主要用于配置開(kāi)發(fā)人員編寫的action。
- struts.xml需要存放在WEB-INF/classes下,模板如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
</struts>
- web.xml文件
- 在Struts 2中,Struts框架是通過(guò)Filter啟動(dòng)的,他在web.xml中的配置如下:
<!-- 配置Struts2 核心 Filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 在StrutsPrepareAndExecuteFilter的init()方法中將會(huì)讀取類路徑下默認(rèn)的配置文件struts.xml完成初始化操作。
- 注意:struts 2 讀取到 struts.xml的內(nèi)容后,以javabean形式存放在內(nèi)存中,以后Struts 2對(duì)用戶的每一次請(qǐng)求處理將使用內(nèi)存中的數(shù)據(jù)。
- Filter 過(guò)濾器是用戶請(qǐng)求和處理程序之間的一層處理程序。它可以對(duì)用戶請(qǐng)求和處理程序響應(yīng)的類容進(jìn)行處理,通常用于權(quán)限、編碼轉(zhuǎn)換等場(chǎng)合。
- ActionSupport 類
- ActionSupport 類為 Action 提供了一些默認(rèn)實(shí)現(xiàn),主要包括預(yù)定義常量、從資源文件中取文本資源、接收驗(yàn)證錯(cuò)誤信息和驗(yàn)證的默認(rèn)實(shí)現(xiàn)。
- 數(shù)據(jù)校驗(yàn)
- Action 繼承了 ActionSupport 類 ,而該類實(shí)現(xiàn)了 Action 、Validateable 、 ValidationAware 、TextProvider、LocaleProvider、Serializable 接口。
- 在Validateable 接口定義了一個(gè) validate() 方法 , 在用戶自定義 Action 類中重寫該方法就可以實(shí)現(xiàn)驗(yàn)證功能。
public class LoginAction extends ActionSupport{
private String username ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
if ( ! username.equals("HelloWorld"))
{
Map request = (Map) ActionContext.getContext().get("request") ;
request.put("name", getUsername()) ;
return SUCCESS;
}
else return ERROR ;
}
//重寫的validate方法
public void validate()
{
//如果名字為空,則把錯(cuò)誤信息天驕的Action類的fileError
if (this.getUsername() == null || this.getUsername().trim().equals(""))
{
addFieldError("username" , "名字不能為空") ;
}
}
}
- 在類中定義了校驗(yàn)方法后,該方法會(huì)在執(zhí)行系統(tǒng)的execute() 方法之前執(zhí)行。如果執(zhí)行該方法后,Action類的fieldError中已經(jīng)包含了數(shù)據(jù)校驗(yàn)錯(cuò)誤信息,將把請(qǐng)求轉(zhuǎn)發(fā)到input邏輯視圖處,所以在 Action配置中也要配置一下。
<action name = "LoginAction" class = "com.cnblogs.jbelial.login.LoginAction" >
<!-- 定義3個(gè)邏輯視圖和物理資源之間的映射 -->
<result name = "input">/login.jsp</result>
<result name = "error">/error.jsp</result>
<result name = "success">/main.jsp</result>
</action>
result中name屬性有下:
1、success :表示請(qǐng)求處理成功后跳轉(zhuǎn)的目標(biāo)頁(yè),該值也是默認(rèn)值;
2、error :表示請(qǐng)求處理失敗后跳轉(zhuǎn)的目標(biāo)頁(yè);
3、none :表示請(qǐng)求處理完成后不跳轉(zhuǎn)到任何頁(yè)面;
4、input :表示輸入時(shí)如果驗(yàn)證失敗應(yīng)該跳轉(zhuǎn)到什么地方;
5、login :表示登錄失敗后跳轉(zhuǎn)的目標(biāo)。
- Struts 2 驗(yàn)證框架的應(yīng)用
- Struts 2 提供了大量的數(shù)據(jù)校驗(yàn)器,包括表單域校驗(yàn)器和非表單域校驗(yàn)器。
- 必填字符串校驗(yàn)器:
該校驗(yàn)器的名字是 requiredstring 其校驗(yàn)規(guī)則定義文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<field name = "username">
<!-- 需要驗(yàn)證的字段的字段名 -->
<field-validators type = "requiredstring">
<!-- 去空格 -->
<param name = "trim">true</param>
<!-- 錯(cuò)誤提示信息 -->
<message>請(qǐng)輸入用戶名</message>
</field-validators>
</field>
</validators>
文件命名:ActionName-validation.xml:其中ActionName 就是需要校驗(yàn)的用戶自定義的Action 類的名字。而且該文件應(yīng)該與Action 類文件放置在同一路徑下。
- 必填校驗(yàn)器
該校驗(yàn)器的名字就是 required 。該校驗(yàn)器與requiredstring 的差別就是 可以有空字符串。配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<!-- 需要驗(yàn)證的字段的字段名 -->
<field name = "username">
<field-validators type = "required">
<!-- 錯(cuò)誤提示信息 -->
<message>請(qǐng)輸入用戶名</message>
</field-validators>
</field>
</validators>
- 整數(shù)校驗(yàn)器
該校驗(yàn)器的名字為 int ,該校驗(yàn)器要求字段的整數(shù)值必須在一定范圍內(nèi)。配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<!-- 需要驗(yàn)證的字段的字段名 -->
<field name = "number">
<field-validators type = "int">
<!-- 數(shù)值的最小值 -->
<param name = "min">50</param>
<!-- 數(shù)值的最大值 -->
<param name = "max">100</param>
<!-- 錯(cuò)誤提示信息 -->
<message>大小必須在50至100之間</message>
</field-validators>
</field>
</validators>
- Struts 2 攔截器:
- Struts 2 框架的絕大部分功能是通過(guò)攔截器來(lái)完成的,當(dāng)F ilterDispatcher攔截到用戶請(qǐng)求后,大量攔截器將會(huì)對(duì)用戶請(qǐng)求進(jìn)行處理,然后調(diào)用用戶自定義的Action 類中的方法來(lái)處理請(qǐng)求。
- 攔截器的配置:
在struts.xml文件中來(lái)定義的,使用<interceptor.../>元素,格式如下:
<interceptor name = "攔截器名" class = "攔截器實(shí)現(xiàn)的類">
<param name = "參數(shù)名">參數(shù)值</param>
</interceptor>
其中<param.../>可以省略,但在有的時(shí)候就需要為其傳入攔截器參數(shù)。
- 有時(shí)候一個(gè)Action要配置不只一個(gè)攔截器,往往多個(gè)攔截器一起使用來(lái)進(jìn)行過(guò)濾。這時(shí)候就要配置幾個(gè)攔截器組成的攔截器棧。定義攔截器棧用
<interceptor-stack.../>,格式如下:
<interceptor-stack name = "攔截器棧名">
<interceptor-ref name = "攔截器一"></interceptor-ref>
<interceptor-ref name = "攔截器二"></interceptor-ref>
<interceptor-ref name = "攔截器三"></interceptor-ref>
</interceptor-stack>
注意:在配置攔截器棧時(shí),用到的攔截器必須是已經(jīng)存在的攔截器。攔截器棧也可以引用攔截器棧。
- 攔截器實(shí)現(xiàn)類:
- Struts 2 提供了一些接口或類供程序員自定義攔截器。如:com.opensymphony.xwork2.interceptor.Interceptor 接口。
- 該接口中有三個(gè)方法:
void init () :用于初始化資源。
String intercept (ActionInvocation invocation) :用于實(shí)現(xiàn)攔截的動(dòng)作。
destroy () :用于銷毀在init()方法中打開(kāi)的資源。

