主要介紹struts2的XML配置方式輸入校驗,結合實例進行說明。
代碼結構:

關鍵代碼:

RegistAction.javapackage com.alfred.regist.action;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class RegistAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private String repassword;
private Integer age;
private Date birthday;
private Date graduation;
public String toRegist() {
System.out.println("run toRegist");
return SUCCESS;
}
@Override
public void validate() {
System.out.println("run validate");
}
public void validateToRegist() {
if (this.hasFieldErrors()) {
System.out.println("already has field error");
}
System.out.println("run validateToRegist");
if (age != null && (age < 20 || age > 100)) {
this.addFieldError("age", "(code)年齡錯誤");
}
}
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;
}
public String getRepassword() {
return repassword;
}
public void setRepassword(String repassword) {
this.repassword = repassword;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Date getGraduation() {
return graduation;
}
public void setGraduation(Date graduation) {
this.graduation = graduation;
}
}

regist.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<!--
校驗規則:
username 不為空 2~5位
password 不為空 3~6位
repassword 與password一致
age 介於20~100歲
birthday 不會空 大於2000-01-01年
graduation 不會空 大於2010-01-01年
-->
<s:actionmessage cssStyle="color:red" />
<s:actionerror cssStyle="color:green;" />
<s:fielderror cssStyle="color:blue;" />
===============
<br />
<s:form action="regist">
<s:textfield label="username" id="username" name="username"></s:textfield>
<s:password label="password" id="password" name="password"></s:password>
<s:password label="repassword" id="repassword" name="repassword"></s:password>
<s:textfield label="age" id="age" name="age"></s:textfield>
<s:textfield label="birthday" id="birthday" name="birthday"></s:textfield>
<s:textfield label="graduation" id="graduation" name="graduation"></s:textfield>
<s:submit value="submit"></s:submit>
</s:form>
</body>
</html>

struts.xml<?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>
<package name="default" extends="struts-default">
<action name="regist"
class="com.alfred.regist.action.RegistAction" method="toRegist">
<result name="success">WEB-INF/jsp/main.jsp</result>
<result name="input">regist.jsp</result>
</action>
</package>
</struts>
使用XML方式檢驗需創建一個XML配置文件,位置在對應的Action同級目錄下,命名規則為:Action名-validatioin.xml。
校驗文件可以有兩種寫法,一種是字段校驗,一種是非字段校驗。字段校驗就是以字段為主,在對應字段配置下添加該字段的校驗器,非字段校驗就是先定義好校驗器,在校驗器下添加字段。如下:

RegistAction-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 type="requiredstring">
<message>(XML)username is not blank</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">2</param>
<param name="maxLength">5</param>
<message>
(XML)username is ${minLength}~${maxLength}
</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>(XML)password is not blank</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">3</param>
<param name="maxLength">6</param>
<message>
(XML)password is ${minLength}~${maxLength}
</message>
</field-validator>
</field>
<field name="repassword">
<field-validator type="fieldexpression">
<param name="expression">
<![CDATA[(password==repassword)]]>
</param>
<message>(XML)two password should be the same!</message>
</field-validator>
</field>
<field name="age">
<field-validator type="required">
<message>(XML)age is not blank</message>
</field-validator>
<field-validator type="int">
<param name="min">20</param>
<param name="max">100</param>
<message>(XML)age is ${min}~${max}</message>
</field-validator>
</field>
<field name="birthday">
<field-validator type="required">
<message>(XML)birthday is not blank</message>
</field-validator>
<field-validator type="date">
<param name="min">2000-01-01</param>
<message>
(XML)birthday is date and greater than ${min}
</message>
</field-validator>
</field>
<field name="graduation">
<field-validator type="required">
<message>graduation is not blank</message>
</field-validator>
<field-validator type="date">
<param name="min">2010-01-01</param>
<message>
(XML)graduation is date and greater than ${min}
</message>
</field-validator>
</field>
</validators>

RegistAction-validation2.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>
<validator type="requiredstring">
<param name="fieldName">username</param>
<message>(XML2)username is not blank</message>
</validator>
<validator type="requiredstring">
<param name="fieldName">password</param>
<message>(XML2)password is not blank</message>
</validator>
<validator type="required">
<param name="fieldName">age</param>
<message>(XML2)age is not blank</message>
</validator>
<validator type="required">
<param name="fieldName">birthday</param>
<message>(XML2)birthday is not blank</message>
</validator>
<validator type="required">
<param name="fieldName">graduation</param>
<message>(XML2)graduation is not blank</message>
</validator>
<validator type="stringlength">
<param name="fieldName">username</param>
<param name="minLength">2</param>
<param name="maxLength">5</param>
<message>(XML2)username is ${minLength}~${maxLength}</message>
</validator>
<validator type="stringlength">
<param name="fieldName">password</param>
<param name="minLength">3</param>
<param name="maxLength">6</param>
<message>(XML2)password is ${minLength}~${maxLength}</message>
</validator>
<validator type="fieldexpression">
<param name="fieldName">repassword</param>
<param name="expression">
<![CDATA[(password==repassword)]]>
</param>
<message>(XML2)two password should be the same!</message>
</validator>
<validator type="int">
<param name="fieldName">age</param>
<param name="min">20</param>
<param name="max">100</param>
<message>(XML2)age is ${min}~${max}</message>
</validator>
<validator type="date">
<param name="fieldName">birthday</param>
<param name="min">2000-01-01</param>
<message>
(XML2)birthday is date and greater than ${min}
</message>
</validator>
<validator type="date">
<param name="fieldName">graduation</param>
<param name="min">2010-01-01</param>
<message>
(XML2)graduation is date and greater than ${min}
</message>
</validator>
</validators>
同時字段校驗和非字段校驗這兩種方法也可以混搭使用,即在同一個校驗配置文件中配置這兩種。
校驗器名詞type可選值可以通過查找xwork的jar包下的default.xml,位置在:展開xwork-core-2.3.24.1.jar->com.opensymphony.xwork2.validator.validators.default.xml。

default.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">
<!-- START SNIPPET: validators-default -->
<validators>
<validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
<validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
<validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
<validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>
<validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>
<validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
<validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
<validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
<validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
<validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
<validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
<validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
<validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
<validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
<validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
<validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>
</validators>
<!-- END SNIPPET: validators-default -->
文件中name就是校驗器名稱,對應的就是type可選值,class是校驗器對應的實現類,校驗器配置的param參數就是實現類中的屬性。

以下是實例程序運行結果:






校驗的執行順序:內置類型轉換->XML校驗器校驗->validateToRegist->validate->toRegist
校驗文件中message的國際化方式:
在Action同級目錄下添加一個ActionName.properties文件,定義key-value,然后,在message標簽的key屬性中填充key值,例如:



結果如下:


這時可以給定義多個ActionName.properties文件以適應瀏覽器使用的不同語言包,例如:ActionName_en_US.properties、ActionName_zh_CN.properties,這樣程序就會根據瀏覽器選擇的語言包自適應提示信息,如果找不到對應語言包的properties文件,將使用默認ActionName.properties的配置。



運行結果:



原理解析:
校驗器基類FieldValidatorSupport,是所有校驗器的父類,提供了fieldName和type屬性。

FieldValidatorSupport.classpackage com.opensymphony.xwork2.validator.validators;
import com.opensymphony.xwork2.validator.FieldValidator;
/**
* Base class for field validators.
*
* @author Jason Carreira
*/
public abstract class FieldValidatorSupport extends ValidatorSupport implements FieldValidator {
private String fieldName;
private String type;
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldName() {
return fieldName;
}
@Override
public void setValidatorType(String type) {
this.type = type;
}
@Override
public String getValidatorType() {
return type;
}
}
校驗器stringlength,對應com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator,繼承自FieldValidatorSupport,提供以下屬性可配置:
private boolean trim = true;
private int maxLength = -1;
private int minLength = -1;
private String maxLengthExpression;
private String minLengthExpression;
private String trimExpression;
public void validate(Object object) throws ValidationException {
String fieldName = getFieldName();
String val = (String) getFieldValue(fieldName, object);
if (val == null || val.length() <= 0) {
// use a required validator for these
return;
}
if (isTrim()) {
val = val.trim();
if (val.length() <= 0) {
// use a required validator
return;
}
}
int minLengthToUse = getMinLength();
int maxLengthToUse = getMaxLength();
if ((minLengthToUse > -1) && (val.length() < minLengthToUse)) {
addFieldError(fieldName, object);
} else if ((maxLengthToUse > -1) && (val.length() > maxLengthToUse)) {
addFieldError(fieldName, object);
}
}
默認trim為true,即校驗字符串類型時默認去除前后空格,maxLength和minLength默認值-1,不判斷最大最小長度。
由此可見,通過繼承FieldValidatorSupport類,我們也可以自定義校驗器,從而實現更符合我們業務邏輯的校驗。
另外在校驗過程中還要注意一些問題:
多方法Action情況如何使用配置文件進行校驗?
Action可能會有多個方法,例如我們上面的toRegist,如果存在多方法的情況下,需要進行校驗的信息肯定是不一樣的,一個配置文件肯定解決不了問題,所有在多方法需要校驗的情況下,我們需要在Action同級別的目錄下,創建命名規則如下的配置文件:ActionName-method-validation.xml 配置文件,比如:RegisterAction中有個toRegist()方法需要校驗,可以創建RegisterAction-toRegist-validation.xml 配置文件進行配置,這個文件就會針對toRegist()方法進行校驗,但是需要注意的是:在調用toRegist()方法時,使用RegisterAction-toRegist-vaidation.xml文件進行校驗后,還會調用RegisterAction-vaidation.xml 文件進行校驗(這點和編碼方式校驗中validate和validateToRegist有些相似),這樣的話,肯定會產生干擾,為了解決這樣問題,可以在開發過程中,不提供RegisterAction-validtion.xml 這樣的文件,對於execute()方法,可以提供一個RegisterAction-execute-validation.xml 文件進行配置校驗。