1、 自定义拦截器
编写步骤
(1) 编写一个类,实现 com.opensymphony.xwork2.interceptor.Interceptor
(2) 实现 intercept 方法(以用户是否登录为例)
public String intercept(ActionInvocation invocation) throws Exception {
//判断用户是否登录
HttpSession session = ServletActionContext.getRequest().getSession();
Object obj = session.getAttribute("user");
if(obj==null){
return "login";
}else{
//表示该方法执行完后执行Action的execute()方法或者执行下一个拦截器
return invocation.invoke();
}
}
(3) 在struts.xml中注册拦截器
<!-- 只是定义拦截器,并没有起作用 -->
<interceptors>
<interceptor name="permissionInterceptor" class="ice.mimosa.interceptor.PermissionInterceptor"></interceptor>
</interceptors>
(4) 然后在Action中引用拦截器
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="permissionInterceptor"></interceptor-ref>
注意:一旦动作中使用了自定义的拦截器,那么默认的就不起作用了。所以还需要引入默认的 defaultStack 拦截器
(5) 若需要多个包中的Action共享拦截器, 则需要通过 Package 来组合拦截器, 然后让其余的包继承该包
<package name="mypackage" extends="struts-default">
<interceptors>
<interceptor name="permissionInterceptor" class="..."></interceptor>
<interceptor name="Interceptor2" class="..."></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="permissionInterceptor"></interceptor-ref>
<interceptor-ref name="Interceptor2"></interceptor-ref>
</interceptor-stack>
</interceptors>
</package>
2、 输入校验
在Struts2中, 可以实现对Action中的所有方法或者指定方法进行校验
(1)采用手工编码的方式校验
1.1 针对该Action的所有的动作方法
a) 动作类继承ActionSupport
b) 覆盖调用public void validate()方法
c) 在validate方法中,编写不符合要求的代码判断,并调用父类的 addFieldError(String fieldName,String errorMessage)
如果fieldError(存放错误信息的Map)有任何的元素,就是验证不通过,动作方法不会执行。Struts2框架会返回到name=input的result
public void validate() {
if (username == null || "".equals(username.trim())) {
// 放入错误信息, struts2框架回去检验
addFieldError("username", "用户名不合法...");
}
if (password == null || "".equals(password.trim()) || !password.matches("\\d{3,6}")) {
addFieldError("password", "密码必须是3-6位数字");
}
}
d) 在name=input指定的页面上使用struts2的标签显示错误信息。
<s:fielderror/>
<s:fielderror fieldName="username"></s:fielderror>
<s:fielderror fieldName="password"></s:fielderror>
<form action="${pageContext.request.contextPath }/validateForm.action" method="post">
用户名:<input type="text" name="username" /><br>
密码:<input type="text" name="password" />
<input type="submit" value="提交" />
</form>
1.2 针对该Action中的指定方法
1.编写步骤与上面相同
2 . 验证方法书写有要求:
public void validateXxx() {…}
Xxx代表的是要验证的动作方法名,其中要把动作方法名的首字母变为大写。
比如查询方法就不需要验证, 所以一般采用针对制定的方法去验证.
1.3 输入校验的流程(类型转换和校验不分家)
1) 类型转换器对请求参数执行类型转化, 并把转换后的值赋值给Action中的属性.
2) 如果在执行类型转换器的过程中出现异常, 系统会将异常信息保存到ActionContext, conversionError拦截器将异常信息封装到filedErrors里. 不管类型转换器是否出现异常, 都会进入第3步.
3) 系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名.
4) 再调用action中的validate()方法.
5) 经过上面4步, 如果系统中的filedErrors存在错误信息(即存放错误信息的集合size大于0), 系统自动将请求转发至名称为input的视图. 否则, 系统将执行action中的处理方法
(2)基于xml的配置方式
实现基于xml配置方式输入校验时, Action也需要继承ActionSupport
1.1 针对所有的方法
在动作类的包中,建立一个名称为:动作简单类名-validation.xml, 比如要验证的动作类名是UserAction — UserAction-validation.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!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 : 内置验证器都是定义好的,在xwork-core.jar
com.opensymphony.xwork2.validator.validators包中的default.xml文件中 -->
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>密码不能为空</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[\d{3,6}]]></param>
<message>密码必须为3-6的数字</message>
</field-validator>
</field>
</validators>
1.2 针对指定的方法
配置文件的名称书写有一定要求。
规则: 动作类名-动作名(struts.xml配置文件中的action的名称)-validation.xml
UserAction-user_add-validation.xml
其余的配置都相同
(3)系统内置校验器
(4)自定义验证器
a、编写一个类,继承FieldValidatorSupport类。
b、在public void validate(Object object)编写你的验证逻辑,不符合要求的就向fieldErrors中放消息
public class _04_myValidate extends FieldValidatorSupport {
@Override
public void validate(Object object) throws ValidationException {
String fieldName = getFieldName();// 取得字段名
String filedValue = (String) getFieldValue(fieldName, object);// 取得用户输入的当前字段的值
if (!isPasswordStrong(filedValue)) {
addFieldError(fieldName, object);
}
}
private static final String GROUP1 = "abcdefghijklmnopqrstuvwxyz";
private static final String GROUP2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String GROUP3 = "0123456789";
protected boolean isPasswordStrong(String password) {
boolean ok1 = false;
boolean ok2 = false;
boolean ok3 = false;
int length = password.length();
for (int i = 0; i < length; i++) {
if (ok1 && ok2 && ok3)
break;
String character = password.substring(i, i + 1);
if (GROUP1.contains(character)) {
ok1 = true;
continue;
}
if (GROUP2.contains(character)) {
ok2 = true;
continue;
}
if (GROUP3.contains(character)) {
ok3 = true;
continue;
}
}
return ok1 && ok2 && ok3;
}
}
c、一定注册你的验证器才能使用
在WEB-INF/classes目录下建立一个名称为 validators.xml 的配置文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator Definition 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">
<!-- 注册自定义的验证器,类似系统提供的default.xml文件一样去注册 -->
<validators>
<validator name="strongpassword" class="mimosa.struts2.b_interceptor._04_myValidate">
</validator>
</validators>
d、日后就可以像使用Struts2提供的16个验证器方式去使用了。在校验的配置文件中通过 type = strongpassword 引入校验器即可
3、国际化
(1) 全局资源文件
1、在WEB-INF/classes目录下建立资源文件, 命名规则
baseName_语言_国家.properties
baseName_语言.properties
baseName.properties(表示默认资源文件)
baseName为基名
2、在Struts.xml文件中进行注册
<constant name="struts.custom.i18n.resources" value="基名" />
3、然后就可以在Jsp页面中进行访问
<s:text name="key"/>也可以通过 <s:i18n> 的标签
4、在Action中访问, Action继承ActionSupport类, 通过getText()函数进行访问
5、若资源文件中有占位符{0} , {1}, … 在jsp中通过<s:param>
标签进行注入
Action中则通过getText(String key,String[] args)访问.
(2) 包范围资源文件
服务于Java类中的包下的动作类的。
取名:package_语言_国家.properties, package是固定写法, 处于该包及子包下的Action都可以访问该资源. 当查找key的消息时, 系统会先从package中的资源文件中查找, 若找不到, 才从struts.custom.i18n.resources指定的资源文件去找.
(3) Action范围资源文件
放到与动作类相同的包中
取名:动作类名语言国家.properties, 通过搜索key值的时候, 也会遵循上述的搜索顺序.
(4) i18n标签
<s:i18n>标签可以直接访问类路径下的资源文件.而无需任何配置
<s:i18n name="基名">
<s:text name="key" />
</s:i18n>
基名为类路径下资源文件的基名
若要访问类路径下某包中的资源文件
<s:i18n name="ice/mimosa/action/package">
<s:text name="key">
<s:param>通配符参数0</s:param>
<s:param>通配符参数1</s:param>
</s:text>
</s:i18n>
package 为访问的资源文件的基名