Struts2中的多个验证方法的共存细节一
在Struts2中默认的,使用validateAbc()作为abc()的验证方法
所以,如果还存在xyz()方法的话,那么它的验证方法就是validateXyz()方法
执行时,首先执行validateAbc()方法
而无论validateAbc()方法执行后的结果如何,都会去执行validate()方法
也就是说,如果一个Action中提供validate()方法的话,那么它是一定会被执行的
执行完validate()之后,如果没有发现存在Field或者Action级别的ERROR的话
那么才会执行相应的业务逻辑的方法,如abc()方法
Struts2中的多个验证方法的共存细节二
很显然这种机制不是很合理。因为不同的业务逻辑存在着不同的验证方式
如果不同的验证方式验证完之后,还要去验证一下validate()的话,显然这是不合理的
这种情况下有两种解决的策略
1..不再复写validate()方法,由于父类的validate()方法的方法体是空的
尽管它也会被调用,但是它什么也不会做,不会对我们的程序造成任何影响
2..重命名validate()方法,即命名为validateExecute()
所以本例若需执行execute()的话,则可通过validateExecute()验证表单
提示Struts2的默认错误信息
如果int或long发生类型转换错误的话,Struts2会将该属性值自动设为零
如果String发生类型转换错误的话,它会将该属性值自动设为null
但若前台页面输入的age是字符串的话,那么它是无法转换成int型的
这时在前台页面就会提示Invalid field value for field "age".信息
在这个错误提示信息中的age对应的是前台页面中<input name="">为age的值
这是因为Struts2在遇到类型转换错误的时候,也就是说无法进行类型转换的时候
struts2框架会自动生成一条错误信息,并将该错误信息放到addFieldError()中
然后就可以通过全局或局部的国际化资源转换文件来自定义更为人性化的错误提示信息
然后就可以在前台使用<s:fielderror/>标签输出资源文件中自定义的错误提示信息
另外,在Struts1.x中若想在页面中提示关于表单填写的信息,则要增加<html:errors/>标签
全局的国际化资源转换文件自定义Struts2提示的错误信息
类型转换出现错误时Struts2中的conversionError拦截器负责将错误封装成表单错误中的Fielderror
在xwork-2.0.4.jar中的com.opensymphony.xwork2包里面有一个xwork-messages.properties文件
将它里面的xwork.default.invalid.fieldvalue属性在资源文件中覆盖就可以输出人性化的信息了
在struts.xml中配置了message.properties之后,就可以建立该文件了
建好后输入xwork.default.invalid.fieldvalue = {0} error
由于是进行资源转换,所以xwork.default.invalid.fieldvalue写法是固定的
而{0}则对应前台页面中<input name="">里面的name值
比如在age输入域中输入字符串之后,就会提示age error
如果在birthday输入域中输入字符串的话,同样会提示birthday error
局部的国际化资源转换文件
全局的资源文件有些时候并不是特别好用,因为它显示的效果过于单一枯板
而Struts2也已经认识到了这一点,因此它又给我们提供了使用局部的资源文件的方式
局部的国际化资源转换文件也是在项目开发中使用的最多的
虽然它显得比较麻烦,但是它能够为用户提供一种更友好的视图表现方式
局部的资源文件必须与它所要验证的类在同一个目录下,并且要与类同名
比如验证RegisterAction的某些属性,那么它必须与RegisterAction位于同一目录下
并且的它名字也必须是RegisterAction.properties,然后编辑它的内容
比如相对于age属性来说invalid.fieldvalue.age = age conversion error
其中invalid.fieldvalue.是固定的,后面跟RegisterAction类中的属性
所以这句话的意思就是:当age发生类型转换错误时,则显示age conversion error信息
并且局部的先级要高于全局的国际化资源转换文件,所以将优先显示局部资源文件中的提示信息
下面是示例工程,这是一个Struts2.0.11应用
首先是web.xml文件
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <welcome-file-list>
- <welcome-file>validateInput.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
然后是用于提供表单输入的validateInput.jsp页面
- <%@ page language="java" pageEncoding="UTF-8"%>
- <%@ taglib prefix="s" uri="/struts-tags"%>
- <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold"/>
- <s:form action="validateInput" theme="simple">
- <table border="9">
- <tr>
- <td>姓名</td>
- <td><s:textfield name="username"/></td>
- </tr>
- <tr>
- <td>密码</td>
- <td><s:password name="password"/></td>
- </tr>
- <tr>
- <td>重复密码</td>
- <td><s:password name="repassword"/></td>
- </tr>
- <tr>
- <td>年龄</td>
- <td><s:textfield name="age"/></td>
- </tr>
- <tr>
- <td>出日</td>
- <td><s:textfield name="birthday"/></td>
- </tr>
- <tr>
- <td>毕业时间</td>
- <td><s:textfield name="graduation"/></td>
- </tr>
- <tr>
- <td> </td>
- <td><s:submit value="输入校验"/></td>
- </tr>
- </table>
- </s:form>
- <!--
- ================================================================================================
- 也可以使用普通<form/>替代<s:form/>来编写上面的第6--37行的表单内容,一样可以实现相同的功能
- ================================================================================================
- 【类型转换与输入校验的流程】
- 1. 首先Struts2对客户端传来的数据进行类型转换
- 2. 类型转换完毕后再进行输入校验
- 3. 如果类型转换和输入校验都没有错误发生,那么进入execute方法,调用商业逻辑
- 注意:如果类型转换不成功,也同样要进行输入校验
- ================================================================================================
- 几乎Struts2的每一个标签都有它的theme属性
- 如果未设置该属性的话,在运行时Struts2会自动生成表格,这样不便于排版
- 我们可以通过设置标签的theme="simple"属性使得它不自动生成表格
- 这是很重要的一个属性,有了它就可以很方便的布局了
- ================================================================================================
- 【theme="simple"】
- 当将<s:form/>设置为theme="simple"时,它的子标签也就不会自动生成表格了
- 而且此时<s:form/>中的自动输出FieldError信息的功能就会失效
- 这时我们可以在页面中添加<s:fielderror/>或者<s:actionerror/>标签来统一显示错误信息
- 并且这个时候所显示的错误提示信息中,总会在前面出现一个黑色圆点
- 如果想把这个圆点去掉的话,是一件比较困难的事情
- 可以查看struts2-core-2.0.11.jar中的template.simple中的fielderror.ftl
- 打开这个模板之后可以发现,我们页面显示的信息都是由这个模板定义的
- 我们也可以手工写这个模板,但这将会是一件相当困难的事情
- 如果想把这个黑色圆点去掉的话,就只能修改这个模板,不过挺困难的,很不好改
- 一般情况下都不会去手动的写这个模板,我们多数都是参考已有模板,然后对其稍稍加工
- ================================================================================================
- -->
当表单输入域均正确时显示的validateSuccess.jsp页面
- <%@ page language="java" pageEncoding="UTF-8"%>
- <%@ taglib prefix="s" uri="/struts-tags"%>
- 姓名:<s:property value="username"/><br/>
- 密码:<s:property value="password"/><br/>
- 年龄:<s:property value="age"/><br/>
- 生日:<s:property value="birthday"/><br/>
- 毕业:<s:property value="graduation"/>
然后是struts.xml文件
- <?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">
- <struts>
- <constant name="struts.custom.i18n.resources" value="message"/>
- <package name="struts2" extends="struts-default">
- <action name="validateInput" class="com.jadyer.action.ValidateInputAction" method="abc">
- <result>/validateSuccess.jsp</result>
- <result name="input">/validateInput.jsp</result>
- </action>
- </package>
- </struts>
用到的核心验证逻辑的ValidateInputAction.java
- package com.jadyer.action;
- import java.util.Calendar;
- import java.util.Date;
- import com.opensymphony.xwork2.ActionSupport;
- @SuppressWarnings({"serial", "unused"})
- public class ValidateInputAction extends ActionSupport {
- private String username;
- private String password;
- private String repassword;
- private int age;
- private Date birthday;
- private Date graduation;
- /* 以上六个属性对应的setter和getter略 */
- // /**
- // * INPUT页面中需要添加<s:actionerror/>标签方可显示此处的错误消息
- // */
- // public String abc() throws Exception {
- // if(null==username || username.trim().equals("")){
- // this.addActionError("用户名不能为空");
- // }else if(!Pattern.matches("^[a-zA-Z][a-zA-Z0-9_]{3,14}$", username)){
- // this.addActionError("用户名必须以字母开始,后面跟字母、数字或下划线,且长度必须为4--15位");
- // }
- // if(null==password || password.equals("")){
- // this.addActionError("密码不能为空");
- // }else if(!Pattern.matches("^[a-zA-Z0-9@#]{4,15}$", password)){
- // this.addActionError("密码可以由 字母、数字、@、# 组成,且长度必须为4--15位");
- // }
- // if(this.hasActionErrors()){
- // return INPUT; //如果在验证的过程中,发现用户输入的内容不合理,则返回输入页面
- // }
- // return SUCCESS;
- // }
- public String abc() throws Exception {
- return SUCCESS;
- }
- /**
- * public void addFieldError(String fieldName, String errorMessage)
- * 第一个参数是页面中表单里的输入域的name值,如<input/>或<s:textfield/>等等
- * 第二个参数是提示信息。这个提示信息显示在第一个参数所对应的字段的正上方居中位置
- * 若页面中提供了<s:fielderror/>标签,那么在<s:fielderror/>的位置就会显示相应的提示信息
- */
- public void validateAbc() {
- if (null == username || username.length() < 6 || username.length() > 10) {
- this.addFieldError("username", "用户名不能为空,且长度必须为6--10位");
- }
- if (null == password || password.length() < 6 || password.length() > 10) {
- this.addFieldError("password", "密码不能为空,且长度必须为6--10位");
- } else if (null == repassword || repassword.length() < 6 || repassword.length() > 10) {
- this.addFieldError("repassword", "重复密码不能为空,且长度必须为6--10位");
- } else if (!password.equals(repassword)) {
- this.addFieldError("password", "输入的重复密码与设定密码不一致");
- }
- if (null != birthday && null != graduation) {
- Calendar c1 = Calendar.getInstance();
- c1.setTime(birthday);
- Calendar c2 = Calendar.getInstance();
- c2.setTime(graduation);
- if (!c1.before(c2)) {
- this.addFieldError("birthday","出生日期应该在毕业时间的前面");
- }
- }
- }
- }
用到的局部的国际化资源转换文件ValidateInputAction.properties
- invalid.fieldvalue.age = /u5E74/u9F84/u5E94/u8BE5/u662F/u4ECB/u4E8E 1 /u5230 100 /u4E4B/u95F4/u7684/u6B63/u6574/u6570
- invalid.fieldvalue.birthday = /u51FA/u751F/u65E5/u671F/u8F93/u5165/u6709/u8BEF
- invalid.fieldvalue.graduation = /u6BD5/u4E1A/u65F6/u95F4/u8F93/u5165/u6709/u8BEF
用到的全局的国际化资源转换文件message.properties
- xwork.default.invalid.fieldvalue = {0} /u8F93/u5165/u6709/u8BEF