=============================================================================
搭建Struts2开发环镜
搭建Struts2环镜时,我们一盘需要做以下几个步骤工作:
1,找到开发Struts2应用需要使用到的jar文件。
2,编写Struts2的配置文件
3,在web.xml中加入Struts2 MVC框架启动配置

>>找到开发Struts2应用需要使用到的jar文件。
大家可以到http://struts.apache.org/download.cgi#struts25101下载struts-2.x.x-all.zip,目前最新版
为2.5.10。下载完后解压文件,开发struts2应用需要依赖的jar文件在解压目录的lib文件夹下。不同
的应用需要的JAR包是不同的。下面给出了开发Struts2程序最少需要的JAR。
struts2-core-2.x.x.jar:Struts2框架的核心类库。
xwork-2.x.x.jar:XWork类库,Struts2在其上构建。
ognl-3.1.x.jar:对象图导航语言(Object Graph Navigation Language),Struts2框架通过其读写对象的属性。
freemarker-2.3.x.jar:Struts2的UI标签的模板使用FreeMarker编写。
commons-logging-1.1.x.jar:ASF出品的日志包,Struts2框架使用这个日志包来支持Log4J和JDK1.4的日志记录。
commons-fileupload-1.3.2.jar:文件上传组件,2.6版本后必须加入此文件。
commons-io-2.x.jar: java.io 的扩展
commons-lang3-3.x.jar:为java.lang包提供扩展
javassist-3.11.x.GA.jar:javassist是用来操作字节码的

>>编写Struts2的配置文件
Struts2默认的配置文件为struts.xml,该文件需要存放在WEB-INF/classes下,该文件的配置模版如下:
<?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>
>>在web.xml中加入Struts2 MVC框架启动配置
在struts1.x中,struts框架是通过Servlet启动的。在struts2中,
struts框架是通过Filter启动的。他在web.xml中的配置如下:
<filter>
<filter-name>action2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
<!-- 自从Struts 2.13以后,下面的FilterDispatcher已经标注为过时
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
-->
</filter>
<filter-mapping>
<filter-name>action2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认
的配置文件struts.xml完成初始化操作。

注意:struts2读取到struts.xml的内容后,以javabean形式存放在内存中,以后struts2
对用户的每次请求处理将使用内存中的数据,而不是每次都读取struts.xml文件。
=============================================================================
Struts.xml配置中的包介绍:
<package name="itcast" namespace="/test" extends="struts-default">
<action name="helloworld" class="cn.itcast.action.HelloWorldAction" method="execute">
<result name="success">/WEB-INF/page/hello.jsp</result>
</action>
</package>
在struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的,它主要用于管理一组业务
功能相关的action。在实际应用中,我们应该把一组业务功能相关的Action放在同一个包下。

配置包时必须指定name属性,该name属性值可以任意取名,但必须唯一,他不对应java的类包,如果其
它包要继承该包,必须通过该属性进行引用。包的namespace属性用于定义该包的命名空间,命名空间作
为该包下Action的路径的一部,如访问上面例子的Action,访问路径为:/test/helloworld.action。
namespace属性可以不配置,对本例而言,如果不指定该属性,默认的命名空间为""(空字符串)。

通常每个包都应该继承struts-defalut包,因为Struts2很多核心的功能都是拦截器来实现。如:从请求中把
请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。struts-default定义了这些拦截
器和Result类型。可以这么说:当包继承struts-default才能使用struts2提供的核心功能。struts-default
包是在struts-core-2.x.x.x.jar文件中的struts-defalut.xml中定义。struts-defalut.xml也是Struts2默认配置文件

包还可以通过abstract="true"定义为抽象包,抽象包中不能包含action。

http://localhost:8080/Struts2/test/helloworld.action
localhost:本地址址。
8080:端口。
Struts2:项目名。
test:package的namespace属性。
helloworld:action的name属性。

=============================================================================
解决struts2配置文件无提示问题:
Window --> Preferences --> MyEclipse --> Files and Editors --> XML
--> XMLCatalog --> Add --> File System --> 在struts2jar包中搜索struts配置文件里面网址后面的struts-x.x.dtd文件
--> Key type --> URL --> Key --> 把struts配置文件网址填上

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

=============================================================================
Action名称的搜索顺序:
1,获得请求路径的URL,例如url是:http://server/struts2/path1/path2/path3/test.action。

2,首先寻找namespace为/path1/path2/path3的package,如果不存在这个package则执行步骤3;如果存
在这个package,则在这个package中寻找名字为tes的action,当在该package下寻找不到action时就会
直接跑到默认的namespace的package里面去寻找action(默认的命名空间为空字符串""),如果在默认
namespace的package里面还寻找不到该action,页面提示找不到action。

3,寻找namespace为/path1/path2的package,如果不存在这个package,则转至步骤4;如果存
在这个package,则在这个package中寻找名字为tes的action,当在该package下寻找不到action时就会
直接跑到默认的namespace的package里面去找名字为test的action,在默认namespace的package里面还寻找不
到该action,页面提示找不到action。

4,寻找namespace为/path1的package,如果不存在这个package则执行步骤5;如果存在这个package,
则在这个package中寻找名字为test的action,当在该package中寻找不到action时就会直接跑到默认
namespace的package里面去找名字为test的action,在默认namespace的package里面还建议找不到该
action,页面提示找不到action

5,寻找namespace为/的package,如果存在这个package,则在这个package中寻找名字为test的action,
当在package中寻找不到action或才不存在这个package时,都会去默认namespace的package里面寻找
action,如果还是找不到,崦面提示找不到action。

=============================================================================
Action配置的各项默认值:
<package name="itcast" namespace="/test" extends="struts-default">
<action name="helloworld" class="cn.itcast.action.HelloWorldAction"
method="execute">
<result name="success">/WEB-INF/page/hello.jsp</result>
</action>
</package>
1>>如果没有为action指定class,默认是ActionSuppory。
2>>如果没有为action指定method,默认执行action中的execute()方法。
3>>如果没有指定result的name属性,默认值为success。

=============================================================================
Action中result的各种转发类型
<action name="helloworld" class="cn.itcast.action.HelloWorldAction"
method="execute">
<result name="success">/WEB-INF/page/hello.jsp</result>
</action>

result配置类似于struts2中的forward,但struts2中提供了多种结果类型,常用的类型有:dispatche(默认值)
、redirect、redirectAction、plainText。

在result中还可以使用${属性名}表达式访问action中的属性,表达式里的属性名对应action中的属性。如下:
<result type="redired">/view.jsp?id=${id}</result>

下面是redirectAction结果类型的例子,如果重定向的action中同一个包下:
<result type="redirectAction">helloworld</result>
如果重定向的action在别的命名空间下:
<result type="redirectAction">
<param name="actionName">helloworld</param>
<param name="namespace">/test</param>
</result>
plaintext:显示原始文件内容,例如:当我们需要原样显示jsp文件源代码的时候,我们可以使用此类型。
<!-- plainText定各显示网页源代码 -->
<action name="plainText">
<result type="plainText">
<param name="location">/index.jsp</param>
<param name="charSet">UTF-8</param><!-- 指定读取文件的编码 -->
</result>
</action>

=============================================================================
指定Struts2处理的请求后缀:
struts2默认使用.action后缀访问Action。其实默认后缀是可以通过常是
"struts.action.extension"进行修改的,例如:我们可以配置Struts2只处
理以.do为后缀的请求路径:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 修改默认.action后缀 -->
<constant name="struts.action.extension" value="com,action"></constant>
</struts>

如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。如:
<constant name="struts.action.extension" value="do,go"/>

细说常量定义:
常量可以在struts.xml或struts.properties中配置,建谇在struts.xml中配置,两中配置方式如下:
在struts.xml文件配置常量
<struts>
<constant name="struts.action.extension" value="do"/>
</struts>

在struts.properties中配置常量
struts.action.extension=do

因为常量可惟在下面多个配置文件中进行定义,所以我们需要了解struts2加载常的搜索顺序:
struts-default.xml
struts-plugin.xml
struts.xml
struts.properties
web.xml
如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值

常用常量介绍:
<!-- 指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法和freemarker、velocity的输入 -->
<constant name"struts.i18n.encoding" value="UTF-8"/>
<!-- 该属性指定需要struts2外理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由struts2处理。
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。-->
<constant name"struts.action.extension" value="do"/>
<!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
<constant name"struts.serve.static.browserCache" value="false"/>
<!-- 当struts的配置文件修改后,系统是否自动别想该文件,默认认值为false(生产环境下使作),开发阶断最好打开 -->
<constant name"struts.configuration.xml.reload" value="true"/>
<!-- 开发模式下使用,这样可以打印出理详细的错误信息 -->
<constant name"struts.dewMode" value="true"/>
<!-- 默认的视图主题 -->
<constant name"struts.ui.theme" value="simple"/>
<!-- 与spring集合时,指定由spring负责action对象的创建 -->
<constant name"struts.objectFactory" value="spring"/>
<!-- 该属性设置struts2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false -->
<constant name"struts.enable.DynamicMethodlnvocation" value="false"/>
<!-- 上传文件的大小限制 -->
<constant name"struts.multipart.maxSize" value="10701096"/>

=============================================================================
Struts2的处理流程与Action的管理方式:
StrutsPrepareAndExecuteFilter是Struts2框架的核心控制器,它负责拦载由<url-paltern>/*</url-pattern>指定的所有用户请求,
当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入
Struts2框架处理,否则Struts2框架将略过该请求的处理。当请求转入Struts2框架处理时会先经过一系列的拦载
器,然后再到Action。
面试题:与Struts1不同,Struts2对用户的每一次请求都会创建一个Action,所以Struts2中的Action是线程安全的。

=============================================================================
自定义在型转换器
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
try {
if (toType == Date.class) {//当字符串向Date类型转换时
String[] params = (String[]) value;
return dateFormat.parse(params[0]);
} else if (toType == String.class) {//当Date转换成字符串时
Date date = (Date) value;
return dateFormat.format(date);
}

} catch (Exception e) {
}
return null;
}
将上面的类型转换器注删除为局部类型转换器:
在Action类所在的包下放置ActionClassName+conversion.properties文件,ActionClassName是Action类型,后
面的-conversion.properties是固定写法,寻于本例而言,文件的名称应为HelloWorldAction-conversion.properties。
属性名称=类型转换器的全类名
寻于本例而言,HelloWorldAction-conversion.properties文件中的内容为:
birthday=cn.itcast.e_action.DateTypeConverter

局部类型转换器
1,继承一个类型转换器进行定义
2,注册局部类型转换器

自定义全局类型转换器:
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
try {
if (toType == Date.class) {// 要转换的参数类型value(birthday),toType(Date)
// 把参数转成字符串数组,再把字符串数据转换成Date类型
String[] params = (String[]) value;
return dateFormat.parse(params[0]);
} else if (toType == String.class) {// 要转换的参数类型value(birthday),toType(Date)
// 把参数转成Date类型,再把Date类型转成字符串
Date date = (Date) value;
System.out.println(date+"String.class:" + toType.getClass());
return dateFormat.format(date);
}

} catch (Exception e) {
}
return null;
}
将上面的类型转换器注册为全局类型转换器:
在WEB-INF/classes下放置xwork-conversion.properties文件。在properties
文件中的内容为:
待转换的类型=类型转换器的全类名
对于本例而言,xwork-conversion.properties文件中的内容为:
java.util.Date=cn.itcast.e_action.DateTypeConverter

=============================================================================
文件上传:
第一步:在WEB-INF/lib下加入commons-fileupload-x.x.x.jar、commons-io-x.x.x.jar。这两个文件可以从
http://commons.apache.org/下载
第二步:把form表的enctype设置为:"multipart/form-data",如下:
<form enctype="multipart/form-data"
action="<%=request.getContextPath()%>/demo/fileUp_execute.action"
method="post">
文件:<input type="file" name="image" /> <input type="submit" value="上传" />
</form>
第三步:
在Action类中添加以下属性:
private File image;// 得到上传的文件
private String imageFileName;// 得到文件的名称
private String imageContentType;// 得到文件的类型

public String execute() throws IOException {
String realpath = ServletActionContext.getServletContext().getRealPath("/images");
System.out.println(realpath);
if (image != null) {
// images/
File savefile = new File(new File(realpath), imageFileName);
if (!savefile.getParentFile().exists()) {
savefile.getParentFile().mkdir();
}
FileUtils.copyFile(image, savefile);
ActionContext.getContext().put("message", "上传成功");
}
return "success";
}

多文件上传:
第一步:在WEB-INF/lib下加入commons-fileupload-x.x.x.jar、commons-io-x.x.x.jar。这两个文件可以从
http://commons.apache.org/下载
第二步:把form表的enctype设置为:"multipart/form-data",如下:
<form enctype="multipart/form-data"
action="<%=request.getContextPath()%>/demo/fileUp_execute.action"
method="post">
文件:<input type="file" name="image" /> <input type="submit" value="上传" />
</form>
第三步:
在Action类中添加以下属性:
private File[] image;// 得到上传的文件
private String[] imageFileName;// 得到文件的名称
private String[] imageContentType;// 得到文件的类型

public String execute() throws IOException {
String realpath = ServletActionContext.getServletContext().getRealPath("/images");
System.out.println(realpath);
if (image != null) {
File saverdir = new File(realpath);

if (!saverdir.exists()) {
saverdir.mkdir();
}
for (int x = 0; x < image.length; x++) {
File savefile = new File(saverdir, imageFileName[x]);
FileUtils.copyFile(image[x], savefile);
}

ActionContext.getContext().put("message", "上传成功");
}
return "success";
}

=============================================================================
自定义拦截器:
<package name="inter" namespace="/demo" extends="struts-default">
<interceptors>
<interceptor name="permission" class="cn.itcast.interceptor.PermissionInterceptor" />
<interceptor-stack name="permissionStack">
<interceptor-ref name="defaultStack" /><!-- 系统拦截器必须 -->
<interceptor-ref name="permission" />
</interceptor-stack>
</interceptors>
<global-results>
<result name="success">/WEB-INF/page/message.jsp</result>
</global-results>
<action name="list_*" class="cn.itcast.h_action.HelloWorldAction"
method="{1}">
<interceptor-ref name="permissionStack" />
</action>
</package>
因为struts2中如文件上伟,数据验证,封装请求参数到action等功能都是由系统默认的defalultStack中的
拦截实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。
如果希望包下的所有action都使用自定义的拦截器,可以通过<defalut-interceptor-ref name="permissionStack"/>把
拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一但我们为该包中的某个action显式指定了某个拦截器,
则默认拦截器不会起作用。

如果用户登录后可以访问action中的所有方法
user.jsp{
//设置用户为登录状态,session
}
如果用户没有登录不允许访问action中的方法,并且提示"你没有权限执行该操作"

退出登录或者没登录前执行步骤:
如果没登录前或者执行了quit.jsp(退出登录),访问list_execute,进入execute方法,message="execute" 返回success,然后执行拦截器permissionStack,然后再permissionStack里从上往下执行,
再执行defaultStack成功后,再执行permission进入permission拦截器内里面的PermissionInterceptor类,
首选获取Object user = ActionContext.getContext().getSession().get("user");,判断其user是空的,
执行ActionContext.getContext().put("message", "你没有权限执行该操作");,覆盖message值为message="你没有权限执行该操作" 返回success,直接给message赋值"你没有权限执行该操作",
message.jsp网页网页显示"你没有权限执行该操作"。

登录成功执行步骤:
如果执行了user.jsp(登录成功),访问list_execute,进入execute方法,message="execute" 返回success,然后执行拦截器permissionStack,然后再permissionStack里从上往下执行,
再执行defaultStack成功后,再执行permission进入permission拦截器内里面的PermissionInterceptor类,
首选获取Object user = ActionContext.getContext().getSession().get("user");,判断其user值是itcast,直接返回success,message值不变,message.jsp网页显示"execute"。
message.jsp网页得到值为"你没有权限执行该操作"。

=============================================================================
输入校验:
手工编写代码实现对acgion中所有方法输入校验:
通过重写validate()方法实现,validate()方法会校验action中所有与execute()方法签名相同的方法。当某个数据
校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action
可以继承ActionSupport),如果系统的fieldError包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以
通过<s:fielderror/>显示失败信息。
validate()使用例子:
@Override
public void validate() {// 会对action中的所有方法进行校验
if (this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空");
}
if (this.mobile == null || "".equals(this.mobile.trim())) {
this.addFieldError("mobile", "手机号不能为空");
} else {
// 格式1,3/5/8,后面是9个数字
if (!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()) {
this.addFieldError("mobile", "手机号格式不正确");
}
}
}

验证失败后,请求转发至input视图:
<result name="input">/index.jsp</result>

在index.jsp页面中使用<s:fielderror/>显示失败信息。

手工编写代码实现对acgion指定方法输入校验:
通过validateXxx()方法实现,validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。当某个数据
校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action
可以继承ActionSupport),如果系统的fieldError包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以
通过<s:fielderror/>显示失败信息。
validate()使用例子:
public void validateUpdate() {// 会对action中的所有方法进行校验
if (this.username == null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空");
}
if (this.mobile == null || "".equals(this.mobile.trim())) {
this.addFieldError("mobile", "手机号不能为空");
} else {
// 格式1,3/5/8,后面是9个数字
if (!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()) {
this.addFieldError("mobile", "手机号格式不正确");
}
}
}

验证失败后,请求转发至input视图:
<result name="input">/index.jsp</result>

在index.jsp页面中使用<s:fielderror/>显示失败信息。

=============================================================================
输入校验流程:
validate()类型转换失败也会跳转到input视图,validateXxx()校验失败也会转到input视图(如果自写写的校验没有问题,那就是类型转换失败)
1,类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。

2,如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,
conversionError拦截器将异常信息添加到fieldErrors里。不管类型是否出现异常,都会进入第3步。

3,系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名。

4,再调用action中的validate()方法

5,经过上面4步,如果系统中fieldErrors存在错误信息(即存放错误信息集合的size大于0),系统自动
将请求转发到名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。

=============================================================================
基于XML配置方式实现对Action的所有方法进行输入校验
使用基于XML配置方江苏实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件
和action类放在同一个包下,文件的取名格式为:ActionClassName-validation.xml,其中ActionClassName
为action的简单类名,-validation为固定写法。如果Action类为cn.itcast.UserAction,那么该文件的取名应为:
UserAction-validation.xml。下面是校验文件的模板:
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">

<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="用户名不能为空" />
</field-validator>
</field>
</validators>
<field>指定action中要交验的属性,<field-validator>指定校验器,上面指定的校验器requiredstring是由系统提供的,系统
提供了能满足大部分验证需求的校验器,这些校验器的定义可以在xwork-x.x.jar中的com.opensymphony.xwork2.validator.validators
下的default.xml中找到。
<message>为校验失败后的提示信息,如果需要国际化,可以为message指定key属性,key的值为资源文件中的key。
在这个校验文件中,对action中字符串类型的username属性进行验证,首先要求调用trim()方法去掉空格,然后判断
是否为空。

注意对于正则表达式不起作用代码进行修改
修改:
<param name="expression"><![CDATA[(\w{4,25})]]></param>
参数名字改为regexExpression了
<param name="regexExpression"><![CDATA[(\w{4,25})]]></param>

=============================================================================
编写校验文件时,不能出现帮助信息
在编写ActionClassName+validation.xml校验文件时,如果出现不了帮助信息,可以按下面方式解决
window --> preferences --> myeclipse --> files and editors --> xml --> xmlcatalog点"add",在出现的窗口中
的location中选"File system",然后在xwork-core-2.3.32解压后的目录中选择xwork-validator-1.0.3.dtd
回到设置窗口的时候不要急着关闭窗口,应把窗口中的Key Type改为URL。Key改为http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd

=============================================================================
Struts2提供的校验器列表
系统提供的校验器如下:
常用:
required、requiredstring、stringlength、regex、int、double、fieldexpression、email
required:必填校验器,要求field的值不能为null。
requiredstring:必填字符串校验器,要求field的值不能为null,并且长度大于0,默认情况下会对字符串去前后空格。
stringlength:字符串长度校验器,要求field的值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,
maxLength参数指定最大长度,trim参数指定校能field之前是否去除字符串前后的空格。
regex:正则表达式校验器,检查被校验的field是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive
参数指定进行正则表达式匹配时,是否区分大小写,默认值为true。
int:整数样验器,要求field的整数值必面在指定范围内,min指定最小值,max指定最大值。
double:双精度浮点校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值。
fieldexpression:字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,
该逻辑表达式基于VAlueStack进行求值,返回true时校验通过,否则不能过。
email:邮件地址校验器,要求如果field的值非空,则必须是合法的邮件地十。
一般:
url、date、conversion、visitor、expression
url:网址校验器,要求如果field的值非空,则必须是合法的url地址。
date:日期校验器,要求field的日期值必胆大心细在指定范围内,min指定最小值,max指定最大值。
conversion:转换校验器,指定在类型转换失败时,提示的错误信息。
visitor:用于校验action中的复合属性,它指定一个校验文件用于校验复合属中的属性。
expression:OGNL表达式校验器,expression参数指定ongl表达式,该逻辑表达式基于ValueStack进行求值,
返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中。

=============================================================================
基于XML配置方式对指定action方法实现输入校验
当校验文件的取名为ActionClassName-validation.xml时,会对action中的所有处理方法实现输入验证。
如果你只需要对action中的某个action方法实现校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,
其中ActionName为struts.xml中action的名称。例如:在实际应用中,常有以下配置:
<package name="itcast" namespace="/person" extends="struts-default">
<action name="list_*" class="cn.itcast.a_action.PersonAction" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/WEB-INF/page/message.jsp</result>
</action>
</package>
PersonAction中有以下两个处理方法:
public String update(){
...
}
public String save(){
...
}
要对update()方法实施验证,校验文件的取名为:PersonAction-list_update-validation.xml
要对save()方法实现验证书,校验文件的取名为:PersonAction-list_save-validation.xml

基于XML校验的一些特点
当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml
两种规则的校验文件时,系统按下面顺序寻找校验文件:
1,ActionClassName-validation.xml
2,ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会所校验文件
里的所有校验规则汇总,然后全部应用于action方法的校验。如果两个校验文件中指定的校验南侧则冲突,
则只使用后面文件中的校验规则。

当action继承了另一个action,父类action的校验文件会先被搜过到。

假设UserAction继承BaseAction:
<action name="user" class="cn.itcast.action.UserAction" menthod="{1}">
</action>

访问上面action,系统先搜父类的校验文件:BaseAction-validation.xml,BaseAction-user-validation.xml,
接着搜索子类的校验文件:UserAction-validation.xml,UserAction-user-validation.xml。
应用于上面action的校验规则为这四个文件的总和。

=============================================================================
国际化
准备资源文件,资源文件的命名格式如下:
baseName_language_country.properties
baseName_language.properties
baseName.properties
其中baseName是资源文件的基本名,我们可以自定义,但是language和country必须是java支持的语言和国家。如:
中国:baseName_zh_CN.properties
美国:baseName_en_US.properties

为应用添加两个资源文件
第一个存放中文:itcast_zh_CN.properties
内容为:welcome="欢迎来到北大青鸟"
第二个存入英语(美国):itcast_en_US.properties
内容为:welcome=welcome to bdqn

对于中文的属性文件,我们编写好后,应该使用jdk提供的native2ascii命令把文件转换为unicode编码的文件。
命令的使用方式如下:
native2ascii 源文件.properties 目标文件.properties

配置全局资源与输入国际化信息:
struts.custom.i18n.resources常量把资源文件定义为全局资源文件,如下:
<constant name="struts.custom.i18n.resources" value="itcast"/>
itcast为资源文件的基本名。

后面我们就可以在页面或在action中访问国际化信息:
a:在jsp页面中使用<s:text name=""/>标签输出国际化信息:
<s:text name="welcome"/>,name为资源文件中的key
b:在Action类中,可以继承ActionSupport,使用getText()方法得到国际化信息,该方法的第一个参数用于
指定资源文件中的key。
c:在表单标签中,通过key属性指定资源文件中的key,如:
<s:textfield name="realname" key="welcome"/>

国际化-输出带点位符的国际化信息
资源文件中的内容如下:
welcome={0},欢迎来到北大青鸟{1}

在jsp页面中输出带点位符的国际信息
<s:text name="welcome">
<s:param>小明</s:param>
<s:param>学习</s:param>
</s:text>

在Action类中获取带点位符的国际化信息,可以getText(String kye,String[] args)
或getText(String key,List<?> args)方法。

国际化-包范围资源文件
在一个大型应用中,整个应用有大量的内容需要实现国际化,如果我们把国际化
的内容都放置在全局资源属性文件中,显然会导致资源文件变的过于庞大、臃肿,
不便于维护,这个时候我们可以针对不同模块,使用包范围来组织国际化文件。

方法如下:
在java的包下放置package_language_county.properties资源文件,package为
固定写法,处于该包及子包下的action都可以访问该资源。当查找到key的消息
时,系统会先从package资源文件查找,当找不到对应的key时,才会从常量
struts.custom.i18n.resources指定的资源文件中寻找

国际化-Action范围资源文件
我们也可以为某个action单独指定资源文件,方法如下:
在Action类所在的路径,放置ActionClassName_language_country.properties资源文件
源文件,ActionClassName为action类的简单名称

当查找指定key的消息时,系统会先从
ActionClassName_language_country.properties资源文件查找,如果没有找到对
应的key,然后没着当前包往上查找基本名为package的的资源文件,一直找到最顶层包。
如果还没有找到对应的key,最后会从常量struts.customi18n.resources指定的资源文件中寻找。

国际化-jsp中直接访问某个资源文件
struts2为我们提供了<s:i18n>标签,使用<s:i18n>标签我们可以在类路径下直接
从某个资源文件中获取国际化数据,而无需任何配置:
<!-- 访问全局范围国际化资源 -->
<s:i18n name="itcast">
<s:text name="welcome">
<s:param>小明</s:param>
<s:param>学习</s:param>
</s:text>
</s:i18n>
itcast为类路径下资源文件的基本名。

如果要访问的资源文件在类路径的某个包下,可以这样访问:
<!-- 访问包范围国际化资源 -->
<s:i18n name="cn/itcast/action/package">
<s:text name="welcome">
<s:param>小明</s:param>
<s:param>学习</s:param>
</s:text>
</s:i18n>
<br/>
上面访问cn.itcast.action包下基本名为package的资源文件。

如果要访问的资源文件在类路径的某个Action,可以这样访问:
<!-- 访问Action范围国际化资源 -->
<s:i18n name="cn/itcast/action/PersonManageAction">
<s:text name="welcome">
<s:param>小明</s:param>
<s:param>学习</s:param>
</s:text>
</s:i18n>
上面访问cn/itcast/action/PersonManageAction下基本名为PersonManageAction的资源文件。
=============================================================================