Struts2 校驗框架
Struts2 和Struts1同樣也提供了校驗框架,但在Struts2 已經不再把校驗框架做爲一個插件,而是已經內置到了Struts2中,而且配置起來更爲簡單方便,功能也更強大。
下面以一個例子來說明Struts2校驗框架的使用。
1在myeclipse 中創建一個web工程,在src目錄下創建struts.xml 配置文件,添加好xml標頭,配置web.xml文件。
1-1.瞭解一下我做的簡單例子需求,實現一個用戶註冊的功能,用戶信息包括用戶名,密碼,確認密碼,年齡,出生日期,畢業日期等信息。在註冊過程需要提供以下校驗規則:
[1] 用戶必填,長度在6-10之間
[2] 密碼和確認密碼必填,兩次輸入密碼要一致長度,在6-10之間
[3] 年齡必須是數字 界於1-150之間
[4] 出生日期和畢業日期必填,且出生日期必須早於畢業日期
要求:使用struts2 提供的xml配置方式進行校驗。
1-2.首先創建一個register.jsp 頁面,代碼如下:
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>register page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<SCRIPT type="text/javascript">
function validate(){
var usernameValue=document.getElementById("username").value;
var passwordValue=document.getElementById("password").value;
var repasswordValue=document.getElementById("repassword").value;
if(usernameValue.length==0){
alert("username should not be blank!");
return false;
}else if(usernameValue.length<6 || usernameValue.length>10){
alert("username should be between 6 and 10 !");
return false;
}
return true;
}
</SCRIPT>
</head>
<body>
<s:fielderror cssStyle="color:red;"/>
<s:form action="register2" theme="simple">
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<td>username</td>
<td><s:textfield name="username" label="usernmae" id="username"/></td>
</tr>
<tr>
<td>password</td>
<td><s:password name="password" label="password" id="password"/></td>
</tr>
<tr>
<td>repassword</td>
<td><s:password name="repassword" label="repassword" /></td>
</tr>
<tr>
<td>age</td>
<td><s:textfield name="age" label="age"/></td>
</tr>
<tr>
<td>birthday</td>
<td><s:textfield name="birthday" label="birthday"/></td>
</tr>
<tr>
<td>graduation</td>
<td><s:textfield name="graduation" label="graduation"/></td>
</tr>
<tr>
<td> </td>
<td><s:submit /></td>
</tr>
</table>
</s:form>
</body>
</html>
顯示如下:
1-3.創建RegisterAction 代碼如下:
package com.snt.struts2.action;
import java.util.Calendar;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class RegisterAction extends ActionSupport {
private String username;
private String password;
private String repassword;
private int age;
private Date birthday;
private Date graduation;
public int getAge() {
return age;
}
public void setAge(int 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;
}
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 String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String execute() throws Exception {
return SUCCESS;
}
/**
* 註冊1方法
* @return
* @throws Exception
*/
public String register1() throws Exception {
return SUCCESS;
}
public String abc()throws Exception{
System.out.println("abc method invoke!");
return SUCCESS;
}
public String xyz()throws Exception{
System.out.println("abc method invoke!");
return SUCCESS;
}
public void validateAbc(){
System.out.println("valide abc()");
}
public void validateXyz(){
System.out.println("valide xyz()");
}
/***
* 當遇到類型轉化時,struts2自動生成一條錯誤信息,放到
* fielderrors 中
*/
public void validateExecute() {
//當用戶直接訪問action時,action的屬性都是null
//防止NullPointException
System.out.println("validate()...........");
if(null==username || username.length()<6 || username.length()>10){
this.addActionError("username invalid!");
}
if(null==password || password.length()<6 || password.length()>10){
this.addActionError("password is invalid!");
}else if(null==repassword || repassword.length()<6 || repassword.length()>10){
this.addActionError("password is invalid!");
}else if(!password.equals(repassword)){
this.addActionError( "tow password is not be same!");
}
if(age<=0 || age>150){
System.out.println("ERROR");
this.addActionError( "age is invalid!");
}
if(null!=birthday && null!=graduation){
Calendar c1=Calendar.getInstance();
c1.setTime(birthday);
Calendar c2=Calendar.getInstance();
c2.setTime(graduation);
if(!c1.before(c2)){
this.addActionError("birthday shoud before graduation!");
}
}
}
public void validateRegister1() {
//當用戶直接訪問action時,action的屬性都是null
//防止NullPointException
System.out.println("validate()...........");
System.out.println("validate()...........");
if(null==username || username.length()<6 || username.length()>10){
this.addFieldError("username", "username is invalid");
}
if(null==password || password.length()<6 || password.length()>10){
this.addFieldError("password", "password is invalid!");
}else if(null==repassword || repassword.length()<6 || repassword.length()>10){
this.addFieldError("password", "password is invalid!");
}else if(!password.equals(repassword)){
this.addFieldError("password", "tow password is not be same!");
}
if(age<0 || age>150){
this.addFieldError("age", "age is invalid!");
}
if(null==birthday){
this.addFieldError("birthday", "birthday invalid!");
}
if(null==graduation){
this.addFieldError("graduation", "graduation invalid!");
}
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","birthday shoud before graduation!");
}
}
}
}
1-4.採用Struts2的檢驗框架需要創建一個配置文件,規則如下,我們需要在與所有要進行校驗的Action同級別目錄下創建一個xml文件,命名必須遵守規則:Action名-validation.xml 文件,對於這個例子就是:RegisterAction-validation.xml做爲校驗的配置文件,下面我創建這個文件:代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring" short-circuit="false">
<param name="trim">true</param>
<message>username shoudld not be blank!</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">10</param>
<message>username should be between ${minLength} and ${maxLength}</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>password should not be balank!</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">10</param>
<message>password should be between ${minLength} and ${maxLength}</message>
</field-validator>
</field>
<field name="repassword">
<field-validator type="requiredstring">
<message>repassword should not be balank!</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">10</param>
<message>repassword should be between ${minLength} and ${maxLength}</message>
</field-validator>
</field>
<field name="repassword">
<field-validator type="fieldexpression">
<param name="expression"> <![CDATA[(password==repassword)]]>
</param>
<message>two password should be the same! </message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>age should be between ${min} and ${max}</message>
</field-validator>
</field>
<field name="birthday">
<field-validator type="required">
<message>birthday should not be blank!</message>
</field-validator>
<field-validator type="date">
<param name="min">2001-01-01</param>
<param name="max">2004-01-01</param>
<message>birthday should be between ${min} and ${max}</message>
</field-validator>
</field>
<field name="graduation">
<field-validator type="required">
<message>graduation should not be blank!</message>
</field-validator>
<field-validator type="date">
<param name="min">2005-01-01</param>
<param name="max">2008-01-01</param>
<message>birthday should be between ${min} and ${max}</message>
</field-validator>
</field>
</validators>
對於Struts2提供的校驗方式有兩種:1 字段校驗 2 非字段校驗
針對字段校驗就如上面xml文件所寫,是針對字段,字段中再配置各種校驗規則。而對於非字段指的是:先定義好校驗器,校驗器中再配置針對那個字段進行校驗。其實兩種校驗方式底層使用機制都是一樣。
比如上面針對用戶的校驗,如下定義:
<field name="username">
<field-validator type="requiredstring" short-circuit="false">
<param name="trim">true</param>
<message>username shoudld not be blank!</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">10</param>
<message>username should be between ${minLength} and ${maxLength}</message>
</field-validator>
</field>
先用<field>標籤描述要校驗的字段,裏面定義校驗器,使用<field-vaidator>標籤,這個標籤中有個type 屬性,這個屬性指是就是校驗規則,比如:requiredstring 就代表必填表的字符串,表明這個信息是用戶必須輸入的。需要注意的是type屬性不是隨便寫的,這個名字會對應struts2 提供的各樣校驗器類。我們查找strust2 原代碼會在xwork jar包中的com.opensymphony.xwork2.validator.validators包下面找到一個default.xml 配置文件,裏面代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator Config 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-config-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="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"/>
</validators>
<!-- END SNIPPET: validators-default -->
這裏面大家可以很清楚的看到,配置是每個校驗器對應的名稱和校驗需要的類,每個校驗都有一個name屬性,這個屬性就是我們在ActionName-validation.xml 配置文件中<field-validator> 標籤type屬性要可以使用的值,同樣我們也可心在com.opensymphony.validator.validators包中找到對應的校驗器類,比如:我們可以打開
com.opensymphony.validator.validators.RequiredStringValidator 類源代碼如下:
/*
* Copyright (c) 2002-2006 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.xwork2.validator.validators;
import com.opensymphony.xwork2.validator.ValidationException;
public class RequiredStringValidator extends FieldValidatorSupport {
private boolean doTrim = true;
public void setTrim(boolean trim) {
doTrim = trim;
}
public boolean getTrim() {
return doTrim;
}
public void validate(Object object) throws ValidationException {
String fieldName = getFieldName();
Object value = this.getFieldValue(fieldName, object);
if (!(value instanceof String)) {
addFieldError(fieldName, object);
} else {
String s = (String) value;
if (doTrim) {
s = s.trim();
}
if (s.length() == 0) {
addFieldError(fieldName, object);
}
}
}
}
在usrename 的必須字段校驗串中有這樣一段配置
<param name="trim">true</param>
大家再年,上面紅色背景顯示的一段代碼,就可以明白,這個參數就是賦值爲這個屬性的。表明校驗時要去掉字符串兩邊的空格。當然如果有其它方法,也可以這樣使用<param>標籤傳參數。<message>標籤中信息是校驗失敗後要顯示的信息。
上面爲username 定義了一個必填字段校驗器外,還添加了一個長度限制的校驗器stringlength 校驗器。其它配置都是一樣的!
上面說過了,字段校驗有兩種,一種是上面所說的字段校驗,另一種是非字段校驗,下面我們看一下:
針對username 的非字段校驗配置如下:
<validator type="requiredstring">
<param name="fieldName">username</param>
<message>username should not be blank</message>
</validator>
<validator type="stringlength">
<param name="fieldName">username</param>
<param name="minLength">6</param>
<param name="maxLength">10</param>
<message>username should be between ${minLength} and
${maxLength}</message>
</validator>
看上面的配置,先定義一個校驗器,使用<validator>標籤,然後在標籤裏配置的參數
<param name="fieldName">username</param>
name 屬性是不變的,使用fieldName 代表字段名,標籤中間的值代表要校驗的字段,下面的<message>標籤中信息是校驗失敗後要顯示的信息。其實非字段校驗和這字段校驗沒什麼區別,只是配置文件不一樣而已,在開發中建議使用字段校驗,會更清晰一點!
1-5.OK這樣配置,整個配置文件都可以生產了,運行測試應用,顯示如下:
OK,校驗測試成功。
另外在校驗過程中還要注意一些問題:
多方法Action情況如何使用配置文件進行校驗?
我們知道大多數據情況下,Action可能會有多個方法,面我們上面所說的都是針對execute()方法進行的校驗,如果存在多方法的情況下,需要進行校驗的信息肯定是不樣的,一個配置文件肯定解決不了問題,所有在多方式需要校驗的情況下,我們需要在Action同級別的目錄下,創建命名規則如下的配置文件:ActionName-method-validation.xml 配置文件,比如:RegisterAction中有個test()方法需要校驗,可以創建
RegisterAction-test-validation.xml 配置文件進行配置,這個文件就會針對tets()方法進行校驗,但是需要注意的是:在調用test()方法時,使用RegisterAction-test-vaidation.xml 文件進行校驗後,還會調用RegisterAction-vaidation.xml 文件進行校驗,這樣的話,肯定會產生干擾,爲了解決這樣問題,可以在開發過程中,不提供RegisterAction-validtion.xml 這樣的文件,對於execute()方法,可以提供一個RegisterAction-execute-validation.xml 文件進行配置校驗。
XML方式校驗與硬編碼方式校驗的選擇|
我們採用了XML 配置文件的方式進行校驗,介是Action中的validate()方法同時也會被執行的,這時一些校驗就可能會重複!所以在開發過程中,我們只採用一種方式,要麼使用XML方式進行校驗,要麼採用硬編碼的方式進行校驗,而不建議混合使用的方式;一般情況下,我們採用XML方式進行校驗,而且XML方式可以滿足我們的需求,在業務特別複雜或校驗粒度比較細的情況下我們可以採用硬編碼的方式校驗。
1.6.Struts2 XML配置方式進行是服務器端校驗,當然在開發過程中我們經常會需要客戶端校驗,Struts2也提供了客戶端校驗功能,使用客戶端校驗,首先頁面中Struts2 標籤的主題不能設爲simple主題,另外form標籤的validate 屬性要改爲true。但是Struts2提供的這種客戶端校驗功能是非常有限的,所有在需要使用客戶端校驗的情況,可以採用javascript 或Ajax的方式進行校驗,會更靈活一點。