原創(chuàng)版權(quán)申明:本文章從本人 csdn 博客轉(zhuǎn)到簡書。
如有轉(zhuǎn)載,請申明:轉(zhuǎn)載自 IT天宇:http://www.itdecent.cn/p/cf2d189c45bf
前言
What ? 最近怎么開始寫后端的博客了?

從去年開始就經(jīng)??吹絼e人提“移動(dòng)開發(fā)寒冬”,而年初投簡歷的時(shí)候更是親身體會,不寫3年經(jīng)驗(yàn)連面試機(jī)會都沒有,那么沒有經(jīng)驗(yàn)或經(jīng)驗(yàn)少的人能怎么辦呢,從一開就找不到工作怎么可能會有經(jīng)驗(yàn)?

然而絕望并沒有用,我算運(yùn)氣好,勉強(qiáng)找到一份工作。
從趨勢來看,近幾年移動(dòng)開發(fā)待遇不會很好,今年發(fā)現(xiàn)到處缺后端,于是決定還是搞后端吧,因?yàn)楦惆沧坎贿^一年,后端的知識還沒忘完(好吧,實(shí)際上以前后端也沒多深入),于是利用下班時(shí)間復(fù)習(xí)后端(好吧,其實(shí)好多是預(yù)習(xí)了●﹏●),并把知識整理出來分享給大家。
目錄
- 環(huán)境搭建
- Action
- 配置詳解
- 通配符和動(dòng)態(tài)方法調(diào)用
- OGNL
- Struts 標(biāo)簽
- Validator
- Interceptor
- 國際化
- 常見例子
正文
<a id="1"> </a>
1.環(huán)境搭建
導(dǎo)包
- 直接下載導(dǎo)入
http://struts.apache.org/download.cgi
可根據(jù)需要選擇 all min src 等包,如果僅僅是學(xué)習(xí),選擇 min 包就夠了
-
版本管理工具導(dǎo)入
- Gradle
compile "org.apache.struts:struts2-core:2.5.10.1" - Maven
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.5.10.1</version> </dependency>
上面的僅僅是核心包,根據(jù)需要可引入其他包,比如注解包
compile "org.apache.struts:struts2-convention-plugin:2.5.10" - Gradle
配置
web.xml
struts2 基于攔截器,因此,配置的第一步是在 WEB-INF/web.xml 中配置 struts2 攔截器。
配置的時(shí)候需要注意,不同的版本的 StrutsPrepareAndExecuteFilter 包路徑不一樣,配置的時(shí)候,可以用 IED 搜索這個(gè)類,復(fù)制路徑。比如 Idea 的搜索類快捷鍵是 Ctrl + N。
-
2.5.x 版本
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
為了防止篇幅過大,其他版本就不寫了。
struts.xml
在 src 目錄下建立 struts.xml,Idea 中需要放到 resources 下。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
</struts>
<a id="2"> </a>
2.Action
HelloAction
類
編寫一個(gè)類繼承 ActionSupport, 并提供一個(gè)無參返回字符串且公開的方法,如下:
public class HelloAction extends ActionSupport {
public String hello() throws Exception {
System.out.println("hello world!");
return SUCCESS;
}
}
配置 Action
類似于 Servlet,struts2 使用 action 來處理請求。
使用 action 需要進(jìn)行配置。
xml 配置
在 struts.xml 的 struts 標(biāo)簽里面配置 action
如下:
<package name="p1" extends="struts-default">
<action name="hello" class="com.ittianyu.web.action.HelloAction" method="login">
<result name="success">hello.jsp</result>
</action>
</package>
action 外面是 package,類似于 java 的包。
這里簡單介紹 action 的屬性,后面配置詳解里會一一介紹大部分標(biāo)簽和屬性。
name: 訪問 action 的名稱,如果沒有配置 namespace,則 根路徑/name 就是 action 的訪問地址。
class 和 method 則是指定 action 的類和方法。
注解配置
使用注解前必須保證 已經(jīng)導(dǎo)入了 struts2-convention-plugin 的包。
在 Action 類上加上 @ParentPackage("struts-default")
在對應(yīng)的方法上加上
@Action(value = "hello", results = {
@Result(name = "success", location="/hello.jsp")})
如下:
@ParentPackage("struts-default")
public class HelloAction extends ActionSupport {
@Action(value = "hello", results = {
@Result(name = "success", location="/hello.jsp")})
public String hello() throws Exception {
System.out.println("hello world!");
return SUCCESS;
}
}
配置好后,就可以通過瀏覽器訪問(根路徑取決于項(xiàng)目配置)
http://127.0.0.1/strut2/hello.action
如果訪問成功,控制臺后打印 hello world!。
向 Action 傳遞參數(shù)
登錄是很常見的 action,這個(gè)時(shí)候一般要向服務(wù)器傳遞 username, password 等。
User
創(chuàng)建一個(gè) User 實(shí)體對象,假設(shè)里面只有 username, password。
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
UserAction
創(chuàng)建一個(gè) UserAction 來處理請求,簡單起見,使用注解方式配置。
@ParentPackage("struts-default")
public class UserAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();
@Action(value = "login", results = {
@Result(name = "success", location="/home.jsp")})
public String login() throws Exception {
System.out.println(user.getUsername());
System.out.println(user.getPassword());
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
實(shí)現(xiàn) ModelDriven 方法,返回 user。
然后在執(zhí)行 login 方法之前,ModelDriven 攔截器會給 user 設(shè)置請求提交的值。
獲取 Servlet Api
使用 ServletActionContext
比如:
ServletActionContext.getRequest();
ServletActionContext.getResponse();
<a id="3"> </a>
3.配置詳解
include
用于引入其他 struts2 配置文件
比如:
<struts>
<include file="struts-part1.xml"/>
<include file="struts-part2.xml"/>
</struts>
package
|名稱 |類型 |默認(rèn) |必須 |描述
|----|-----|-----|----|-----|---
|name |string |無 |yes |包的名稱
|extends |string |無 |no |這個(gè)包所繼承的父包名稱.一般繼承 struts-default
|namespace |string |/ |no |包的命名空間,如果配置了,在訪問時(shí)要加上包名
|abstract |boolean |false |no |是否是抽象包,如果是,專門設(shè)計(jì)來被繼承,一般配置了自己的攔截器棧時(shí),會設(shè)計(jì)基礎(chǔ)包。
action
|名稱 |類型 |默認(rèn) |必須 |描述
|----|-----|-----|----|-----|---
|name |string |無 |yes |動(dòng)作的名稱
|class |string |com.opensymphony.xwork2.ActionSupport |no |綁定的動(dòng)作類。若不配置,則為默認(rèn)返回 success 的動(dòng)作類。
|method |string |execute |no |動(dòng)作綁定的方法
|converter |string |無 |no |動(dòng)作的類型轉(zhuǎn)換器
result
<result> 是 <action>的一個(gè)子元素,用于指定 action 的結(jié)果視圖。
|名稱 |類型 |默認(rèn) |必須 |描述
|----|-----|-----|----|-----|---
|name |string |success |no |對應(yīng)動(dòng)作方法的返回值
|type |string |dispatcher |no |結(jié)果類型。struts定義的結(jié)果類型有10種。
type 類型
|序號 |結(jié)果類型 |取值 |描述
|----|-----|-----|----|-----
|1 |Chain Result |chain |轉(zhuǎn)發(fā)方式轉(zhuǎn)到一個(gè)antion
|2 |Dispatcher Result |dispatcher | 轉(zhuǎn)發(fā)到一個(gè)頁面
|3 |FreeMarker Result |freemarker |
|4 |HttpHeader Result |httpheader |
|5 |Redirect Result |redirect | 重定向到一個(gè)頁面
|6 |Redirect Action Result |redirectAction |重定向轉(zhuǎn)到一個(gè)action
|7 |Stream Result |stream | 輸出流,一般用于下載
|8 |Velocity Result |velocity |
|9 |XSL Result |xslt |
|10 |PlainText Result |plainText |常用于顯示個(gè)別頁面的源碼
global-results
包內(nèi)全局的結(jié)果視圖,包內(nèi) action 沒有配置 result 時(shí),會使用全局結(jié)果視圖。一般是在基礎(chǔ)包里面配置,比如全局的登錄驗(yàn)證。
interceptors
用于聲明攔截器。
在 interceptors 中配置 interceptor, interceptor-stack,interceptor-ref 等聲明攔截器。
default-interceptor-ref
用于配置包的默認(rèn)攔截器。
constant
用于配置 struts2 中的常量。
<a id="4"> </a>
4.通配符和動(dòng)態(tài)方法調(diào)用
通配符
struts2 中 action 的 name 支持通配符 *。
用于匹配0個(gè)或多個(gè)字符。
舊版中可以直接使用,在新版中,需要啟用通配符。
在 package 開頭加上
<!--動(dòng)態(tài)方法配置,2.5之后額外配置允許的方法名-->
<global-allowed-methods>regex:.*</global-allowed-methods>
此外還可以通過 {n} 來引用 匹配的值。
<action name="*_*" class="com.ittianyu.javaeetest.web.action.{2}Action" method="{1}{2}">
<result name="success">/{1}{2}.jsp</result>
</action>
如上配置,我們訪問 hello_World 時(shí),會自動(dòng)匹配方法 helloWorld,并在方法執(zhí)行完成后,轉(zhuǎn)發(fā)到 helloWorld.jsp
動(dòng)態(tài)方法調(diào)用
struts2 支持動(dòng)態(tài)指定 action所綁定的方法名,也就是不需要配置 action 的 method。
在請求中使用 !分割,后面寫調(diào)用的方法名。
比如:
http://127.0.0.1/struts2/user!add
默認(rèn)是關(guān)閉的,要使用需要配置。在 struts 標(biāo)簽下加上:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<a id="5"> </a>
5.OGNL
OGNL 是 Object Graph Navigation Language (對象圖形導(dǎo)航語言)的縮寫。
主要用來訪問 棧 和 map 中的對象。
- 支持對象方法調(diào)用,如 xxx.doSomeSpecial();
- 支持類靜態(tài)的方法調(diào)用和值訪問,表達(dá)式的格式:
@[類全名]@[方法名 | 值名],例如:
但需要設(shè)置 struts.ognl.allowStaticMethodAccess=true@java.lang.String@format('foo %s', 'bar') 或 @tutorial.MyConstant@APP_NAME; - 支持賦值操作和表達(dá)式串聯(lián),如 price=100, discount=0.8,
price*discount,這個(gè)表達(dá)式會返回80; - 訪問OGNL上下文(OGNL context)和ActionContext;
- 操作集合對象。
在 jsp 中使用 OGNL 需要引入 struts tag lib。
<%@ taglib prefix="s" uri="/struts-tags" %>
然后使用 標(biāo)簽 s:property:
<s:property value="'hello world'"/>
使用引號引起來表示字符串,否則就是 OGNL 表達(dá)式
ValueStack
ValueStack 實(shí)際是一個(gè)接口,在 Struts2 中利用OGNL時(shí),實(shí)際上使用的是該接口實(shí)現(xiàn)類 OgnlValueStack。
每個(gè) Action 類的對象實(shí)例都有一個(gè) ValueStack 對象,用于保存參數(shù)或結(jié)果。
在 ValueStack 對象的內(nèi)部有兩個(gè)邏輯部分:
- ObjectStack: Struts 把動(dòng)作和相關(guān)對象壓入 ObjectStack 中,看作 List 容器。
- ContextMap: Struts 把各種各樣的映射關(guān)系存入 ContextMap 中,看作 Map 容器。
Struts2 會把下面這些對象存入 ContextMap 中
- parameters: 該 Map 中包含當(dāng)前請求的請求參數(shù)
- request: 該 Map 中包含當(dāng)前 request 對象中的所有屬性
- session: 該 Map 中包含當(dāng)前 session 對象中的所有屬性
- application:該 Map 中包含當(dāng)前 application 對象中的所有屬性
- attr: 該 Map 按如下順序來檢索某個(gè)屬性: request, session, application
訪問 ValueStack
- ObjectStack: 直接通過元素的名稱進(jìn)行訪問。
- ContextMap: 需要在開頭加一個(gè)
#。
比如 ObjectStack 和 ContextMap 中都存放了一個(gè) User,而 User
有屬性 username,那么我們可以通過如下代碼進(jìn)行訪問:
jsp 中:
<%--不加修飾符是在棧中查找對象是否有g(shù)etUsername方法
可以通過[n].來指定從第幾個(gè)開始查找,n從0開始
如果沒找到,就會報(bào)錯(cuò)
--%>
<s:property value="username" />
<%--加修飾符# 是在 map 中查找 key 為 user 的 值
如果存在 session 中,則訪問路徑為 #session.user.username
--%>
<s:property value="#user.username" />
Action 中:
ValueStack vs = ActionContext.getContext().getValueStack();
// setValue 方法的第一個(gè)參數(shù)是 OGNL 表達(dá)式,不加#表示放到棧中
vs.setValue("name", "Mike");// 在棧中查找是否有對象有 setName 方法
vs.setValue("#name", "Mike");// 往 map 中存入 key 為 name,值為 Mike 數(shù)據(jù)。
// set 方法是對 棧 進(jìn)行操作
// 如果棧頂是 map,則把數(shù)據(jù)放入map,否則在棧頂新建一個(gè) map,并存入數(shù)據(jù)。
vs.set("username", "Jane");
# $ % 的使用
-
1、取 contextMap 中 key 時(shí)使用,例如
<s:property value="#name" />
2、OGNL 中創(chuàng)建Map對象時(shí)使用,例如:<s:radio list="#{'male':'男','female':'女'}" /> - $
1、在JSP中使用EL表達(dá)式時(shí)使用,例如${name}
2、在xml配置文件中,編寫OGNL表達(dá)式時(shí)使用,例如文件下載時(shí),文件名編碼。struts.xml——>${@java.net.URLEncoder.encode(filename)} - %
在struts2中,有些標(biāo)簽的value屬性取值就是一個(gè)OGNL表達(dá)式,例如<s:property value="OGNL Expression" />
還有一部分標(biāo)簽,value屬性的取值就是普通字 符串,例如<s:textfield value="username"/>,如果想把一個(gè)普通的字符串強(qiáng)制看成時(shí)OGNL,就需要使用%{}把字符串套起來。
例如<s:textfield value="%{username}"/>。當(dāng)然在<s:property value="%{OGNL Expression}" />也可以使用,但不會這么用。
投影
- “?#”:過濾所有符合條件的集合,如:users.{?#this.age > 19};
- “#”:過濾第一個(gè)符合條件的元素,如:users.{#this.age > 19};
- “$#”:過濾最后一個(gè)符合條件的元素,如:users.{$#this.age > 19}
<a id="6"> </a>
6.Struts 標(biāo)簽
表單標(biāo)簽
常見的表單標(biāo)簽在 struts2 中都有
比如: form,textfield,password,checkbox,checkboxlist ,hidden,submit,reset 等。
<s:form action="register">
<s:textfield name="username" label="用戶名" requiredLabel="true" requiredPosition="left"/>
<s:password name="password" label="密碼"/>
<s:textfield name="birthday" label="生日"/>
<s:checkbox name="married" value="true" label="已婚"/>
<s:checkboxlist list="{'吃飯','睡覺','寫代碼'}" name="hobby" label="愛好" />
<s:select list="#{'BJ':'北京','SH':'上海','SZ':'深圳'}" label="城市" headerKey="" headerValue="---請選擇城市---"/>
<s:radio name="gender" list="#{'male':'男','female':'女'}" label="性別" value="'male'"/>
<s:textarea label="描述" rows="5" cols="30"/>
<s:submit value="注冊" />
<s:reset value="重置" />
</s:form>
set
<%-- set 屬性詳解
value: ognl 表達(dá)式,會存入 map 中
var:作為存入 map 數(shù)據(jù)的 key
scope:指定存入的是哪個(gè) map,有 application,session,request,page,action
--%>
<%-- 并不會往 map 中存入任何值,因?yàn)?value 被解釋為 OGNL 之后是非法的,所以結(jié)果是空 --%>
<s:set value="Mike" var="name" scope="session"/>
<%-- 加上單引號之后,解釋為字符串,存到 session 中 --%>
<s:set value="'Mike'" var="name2" scope="session"/>
<%-- 不寫 scope 默認(rèn)存到 request 和 contextMap 中了 --%>
<s:set value="'Mike'" var="name3"/>
action
<%-- action 屬性詳解
name: action 名稱
executeResult: 是否執(zhí)行 action
一般用于調(diào)用其他 action 并在頁面上顯示結(jié)果
--%>
<s:action name=="action1" executeResult="true">
if elseif else
<%--存入一個(gè)成績--%>
<s:set var="grade" value="90"/>
<s:if test="#grade<60">差</s:if>
<s:elseif test="#grade<80">中</s:elseif>
<s:else>優(yōu)秀</s:else>
url a
<%-- s:url 屬性詳解
value: 輸出的 value 值。不是 OGNL 表達(dá)式
action: action 名稱
var: 如果寫了,就會把 action 的地址存到 contextMap 中,var 作為 key。
--%>
<%-- 指定 value 直接在頁面輸出 value的值 --%>
<s:url value="哈哈哈"/> <br/>
<%-- 指定 action 在頁面輸出 action 的完整地址 --%>
<s:url action="addUser1"/> <br/>
<%-- 指定了 var 則存到 map 中 --%>
<s:url action="addUser1" var="url">
<%--可定義參數(shù),相當(dāng)于get表單的地址一樣--%>
<s:param name="name" value="'張三'"/>
</s:url>
a 標(biāo)簽和 url 類似
<a id="7"> </a>
7.Validator
struts2為我們共內(nèi)置了16個(gè)驗(yàn)證器,且全部是基于字段的驗(yàn)證器。
required
驗(yàn)證字段的值是不是 null。注意,不是空字符串或空白字符串。
<validators>
<field name="password">
<field-validator type="required">
<message>The password field is required!</message>
</field-validator>
</field>
</validators>
requiredstring
驗(yàn)證字段的值既不是null、也不是空白。
參數(shù):
- fieldName:要驗(yàn)證的字段名
- trim:是否去掉首尾空格
<validators>
<field name="userName">
<field-validator type="requiredstring">
<message>Please input the userName!</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<param name="trim">false</param>
<message>Please input the password!</message>
</field-validator>
</field>
</validators>
int
驗(yàn)證某個(gè)字段的值是否可以被轉(zhuǎn)換為一個(gè)整數(shù)。還可以驗(yàn)證是否在允許的范圍內(nèi)。
參數(shù):
- fieldName:要驗(yàn)證的字段名
- min:允許的最小值
- max:允許的最大值
基于字段的驗(yàn)證
<validators>
<field name="age">
<field-validator type="int">
<param name="min">18</param>
<param name="max">60</param>
<message>The age must be between ${min} and ${max}</message>
</field-validator>
</field>
</validators>
基于驗(yàn)證器的驗(yàn)證
<validators>
<validator type="int">
<param name="fieldName">age</param>
<param name="min">18</param>
<param name="max">60</param>
<message>The age must be between ${min} and ${max}</message>
</validator>
</validators>
long short
同 int
double
用來驗(yàn)證某個(gè)字段的值是否可以被轉(zhuǎn)換為一個(gè)雙精度浮點(diǎn)數(shù)。還可驗(yàn)證是否在允許的范圍內(nèi)。
參數(shù):
- fieldName:要驗(yàn)證的字段名
- minInclusive:允許的最小值,包含最小值
- maxInclusive:允許的最大值,包含最大值
- minExclusive:允許的最小值,不包含最小值
- maxExclusive:允許的最大值,不包含最大值
<validators>
<field name="percentage1">
<field-validator type="double">
<param name="minInclusive">20.1</param>
<param name="maxInclusive">50.1</param>
<message> The age must be between ${ minInclusive } and ${ maxInclusive }(含)</message>
</field-validator>
</field>
<field name="percentage2">
<field-validator type="double">
<param name="minExclusive">0.345</param>
<param name="maxExclusive">99.987</param>
<message> The age must be between ${ minExclusive } and ${ maxExclusive }(不含)</message>
</field-validator>
</field>
</validators>
date
用來確保給定的日期字段的值在指定的范圍內(nèi)。
參數(shù):
- fieldName:要驗(yàn)證的字段名
- min:允許的最小值,包含最小值
- max:允許的最大值,包含最大值
<validators>
<field name="birthday">
<field-validator type="date">
<param name="min">2011-01-01</param>
<param name="max">2011-12-31</param>
<message>日期必須為2011年</message>
</field-validator>
</field>
</validators>
expression
用于驗(yàn)證是否滿足一個(gè)OGNL表達(dá)式。這是一個(gè)非字段的驗(yàn)證。只有給定的參數(shù)的返回值是true時(shí)才能驗(yàn)證通過。驗(yàn)證不通過時(shí)產(chǎn)生一個(gè)動(dòng)作錯(cuò)誤,因此要顯示該錯(cuò)誤,需要使用<s:actionerror/>標(biāo)簽。
<validators>
<validator type="expression">
<param name="expression">
maxNumber>minNumber
</param>
<message>最大值必須大于最小值</message>
</validator>
</validators>
field expression
用于驗(yàn)證某個(gè)字段是否滿足一個(gè)OGNL表達(dá)式。這是一個(gè)基于字段的驗(yàn)證。只有給定的參數(shù)的返回值是true時(shí)才能驗(yàn)證通過。驗(yàn)證不通過時(shí)產(chǎn)生一個(gè)字段錯(cuò)誤。
參數(shù):
- fieldName:要驗(yàn)證的字段名
- expression:OGNL表達(dá)式,只有該表達(dá)式為true才能驗(yàn)證通過
<validators>
<field name="maxNumber">
<field-validator type="fieldexpression">
<param name="expression">
maxNumber>100
</param>
<message>最大值必須大于最小值1</message>
</field-validator>
</field>
</validators>
用來驗(yàn)證給定的字段是否符合一個(gè)Email的規(guī)范。它的正則表達(dá)式為
\\b(^[_A-Za-z0-9-](\\.[_A-Za-z0-9-])*@([A-Za-z0-9-])+((\\.com)|(\\.net)|(\\.org)|(\\.info)|(\\.edu)|(\\.mil)|(\\.gov)|(\\.biz)|(\\.ws)|(\\.us)|(\\.tv)|(\\.cc)|(\\.aero)|(\\.arpa)|(\\.coop)|(\\.int)|(\\.jobs)|(\\.museum)|(\\.name)|(\\.pro)|(\\.travel)|(\\.nato)|(\\..{2,3})|(\\..{2,3}\\..{2,3}))$)\\b
<validators>
<field name="email">
<field-validator type="email">
<message>請輸入正確的郵箱</message>
</field-validator>
</field>
</validators>
url
用來驗(yàn)證給定的字段值是否是一個(gè)合法的URL地址。
<validators>
<field name="url">
<field-validator type="url">
<message>請輸入正確的地址</message>
</field-validator>
</field>
</validators>
visitor
該驗(yàn)證程序可以提高代碼的可重用性,你可以利用它把同一個(gè)驗(yàn)證程序配置文件用于多個(gè)動(dòng)作。
<validators>
<field name="streetName">
<field-validator type="requiredstring">
<message>請輸入正確街道地址</message>
</field-validator>
</field>
</validators>
<validators>
<field name="address">
<field-validator type="visitor">
<message>Address:</message>
</field-validator>
</field>
</validators>
stringlength
用來驗(yàn)證一個(gè)非空的字段值是不是有足夠的長度。
regex
用來檢查給定字段是否與給定的正則表達(dá)式相匹配。正則表達(dá)式的詳細(xì)內(nèi)容可以參考 JDK 的 java.util.regex.Pattern 類。
參數(shù):
- fieldname:要驗(yàn)證的字段名
- expression:正則表達(dá)式
- caseSensitive:是否區(qū)分大小寫的情況,默認(rèn) true
- trim:是否去掉首尾空格,默認(rèn) true
<validators>
<field name="userName">
<field-validator type="regex">
<param name="expression"><![CDATA[([aAbBcCdD][123][eEfFgG][456])]]></param>
<message> 用戶名必須符合規(guī)范</message>
</field-validator>
</field>
</validators>
<a id="8"> </a>
8.Interceptor
Struts2 攔截器在訪問某個(gè) Action 方法之前或之后實(shí)施攔截, Struts2 攔截器是可插拔的, 攔截器是 AOP 的一種實(shí)現(xiàn).
常用攔截器
- conversionError:將錯(cuò)誤從ActionContext中添加到Action的屬性字段中。
- fileUpload:提供文件上傳功能
- i18n:記錄用戶選擇的locale
- model-driven:如果一個(gè)類實(shí)現(xiàn)了ModelDriven,將getModel得到的結(jié)果放在Value Stack中。
- params:將請求中的參數(shù)設(shè)置到Action中去。
- servletConfig:提供訪問HttpServletRequest和HttpServletResponse的方法,以Map的方式訪問。
- token:避免重復(fù)提交
- validation:使用 action-validation.xml 文件中定義的內(nèi)容校驗(yàn)提交的數(shù)據(jù)。
- workflow:調(diào)用 Action 的 validate 方法,一旦有錯(cuò)誤返回,重新定位到 INPUT 視圖
自定義攔截器
- 自定義攔截器
public class PermissionInterceptor implements Interceptor { private static final long serialVersionUID = -5178310397732210602L; public void destroy() { } public void init() { } public String intercept(ActionInvocation invocation) throws Exception { System.out.println("進(jìn)入攔截器"); if(session里存在用戶){ String result = invocation.invoke(); }else{ return “l(fā)ogon”; } //System.out.println("返回值:"+ result); //return result; } } - 在 struts.xml 文件中配置自定義的攔截器
<package name="itcast" namespace="/test" extends="struts-default"> <interceptors> <interceptor name=“permission" class="cn.itcast.aop.PermissionInterceptor" /> <interceptor-stack name="permissionStack"> <interceptor-ref name="defaultStack" /> <interceptor-ref name=" permission " /> </interceptor-stack> </interceptors> <action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}"> <result name="success">/WEB-INF/page/hello.jsp</result> <interceptor-ref name="permissionStack"/> </action> </package>
<a id="9"> </a>
9.國際化
struts2 中使用的 properties 文件來做國際化
配置資源包
- 全局資源包
<!--
在struts.xml 中配置常量指定全局字符串包位置
-->
<constant name="struts.custom.i18n.resources" value="com.ittianyu.i18n.strings" />
- 包范圍的資源包:把 資源包放在某包下面,命名為:
package_語言代碼_國家代碼.properties - 局部消息資源包:把 資源包放在某動(dòng)作類路徑下,命名為:
動(dòng)作類名稱_語言代碼_國家代碼.properties
資源包的使用順序:局部 > 包范圍 > 全局
讀取資源包
- Action
public class I18nAction extends ActionSupport { public String execute() { String value = getText("key"); } } - jsp
<s:text name="key"/>
手動(dòng)指定讀取的資源包
當(dāng)注定的包下沒有找到指定的值時(shí),會按順序搜索配置了的資源包
<s:i18n name="com.xxxx.package">
<s:text name="key"/>
</s:i18n>
<a id="10"> </a>
10.常見例子
防重復(fù)提交
-
使用重定向,避免刷新就提交
<result type="redirect">/success.jsp</result> -
使用 tokensession 或 token 攔截器
表單中加入<s:token /><s:form action="login"> <s:token /> </s:form>配置中加入 tokensession 攔截器
<action name="login" class="xxxx"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="tokensession" /> <result type="redirect">/success.jsp</result> </action>token 和 tokensession 功能一樣,但有一些差別。
token 攔截到重復(fù)提交后,會轉(zhuǎn)向invalid.token結(jié)果視圖
而 tokensession 攔截之后不轉(zhuǎn)向任何視圖
上傳
html
<s:form action="upload.action" enctype="multipart/form-data">
<s:textfield name="username" label="用戶名"/>
<s:file name="photo" label="照片"/>
<s:submit value="上傳"/>
</s:form>
action
public class UploadAction extends ActionSupport{
public String username;
public File photo;
public String photoFileName;// 上傳文件名。變量命名規(guī)格 字段名+FileName
public String photoContentType;// 上傳文件的MIME類型。變量命名規(guī)格 字段名+ContentType
public String upload() {
// 獲取文件存儲目錄
ServletContext servletContext = ServletActionContext.getServletContext();
String path = servletContext.getRealPath("/WEB-INF/files");
File file = new File(path);
if (!file.exists())
file.mkdirs();
// 存儲到目標(biāo)路徑
photo.renameTo(new File(file, photoFileName));
return NONE;
}
}
修改上傳文件大小限制
<!--限制上傳最大尺寸為 1048576 byte-->
<constant name="struts.multipart.maxSize" value="1048576"/>
限制上傳文件擴(kuò)展名
<action name="upload" class="com.ittianyu.javaeetest.web.action.UploadAction" method="upload">
<interceptor-ref name="defaultStack">
<param name="fileUpload.allowedExtensions">jpg,png</param>
</interceptor-ref>
<result name="input">upload.jsp</result>
</action>
多文件上傳需要把
public File photo;
public String photoFileName;// 上傳文件名。變量命名規(guī)格 字段名+FileName
public String photoContentType;// 上傳文件的MIME類型。變量命名規(guī)格 字段名+ContentType
改成,也就是改成數(shù)組
public File[] photo;
public String[] photoFileName;// 上傳文件名。變量命名規(guī)格 字段名+FileName
public String[] photoContentType;// 上傳文件的MIME類型。變量命名規(guī)格 字段名+ContentType
下載
action
public class DownloadAction extends ActionSupport {
public InputStream inputStream;
public String filename;
public String download() throws Exception{
// 找到文件路徑
String path = ServletActionContext.getServletContext().getRealPath("/WEB-INF/files/1.jpg");
// 包裝成流
inputStream = new FileInputStream(path);
// 設(shè)置瀏覽器接收時(shí)文件名
filename = "圖片.jpg";
return SUCCESS;
}
}
配置
<action name="download" class="com.ittianyu.javaeetest.web.action.DownloadAction" method="download">
<result name="success" type="stream">
<!--下載類型為 bin-->
<param name="contentType">application/octet-stream</param>
<!--下載打開方式-->
<param name="contentDisposition">attachment;filename=${@java.net.URLEncoder@encode(filename, "UTF-8")}
</param>
<!--流名稱-->
<param name="inputName">inputStream</param>
</result>
</action>