struts2对用户输入数据的校验方法有两种方式,一种是通过编码的方式,另一种则是通过使用XML配置方式。
主要介绍struts2编码方式的输入校验,结合实例进行说明。
代码结构:
关键代码:
RegistAction.javapackage com.alfred.regist.action;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class RegistAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private static final SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd");
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");
this.addActionMessage("进行输入校验");
if (username == null || username.trim().length() < 2
|| username.trim().length() > 5) {
this.addFieldError("username", "用户名格式错误");
}
if (password == null || password.trim().length() < 3
|| password.trim().length() > 6) {
this.addFieldError("password", "密码格式错误");
}
if (repassword == null || !password.equals(repassword)) {
this.addFieldError("repassword", "确认密码需与密码相同");
}
if (age == null || age < 20 || age > 100) {
this.addFieldError("age", "年龄错误");
}
if (birthday == null) {
this.addFieldError("birthday", "出生日期不能为空");
}
if (graduation == null) {
this.addFieldError("graduation", "毕业日期不能为空");
}
if (birthday != null && graduation != null
&& (graduation.compareTo(birthday) < 0)) {
this.addFieldError("birthday", "出生日期不能小于毕业日期");
}
if (this.hasFieldErrors()) {
this.addActionError("action 产生了error");
}
}
public void validateToRegist() {
if (this.hasFieldErrors()) {
System.out.println("already check field");
}
System.out.println("run validateToRegist");
}
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 大于2007-01-20
graduation 大于出生日期
-->
<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>
RegistAction.properties:
struts2的ActionSupport提供了validate这种输入校验方法用于对用户输入的数据进行检验,在将用户数据传递到具体的action处理方法(toRegist)前会先调用validate方法进行输入校验,同时用户也可以自己定义对应方法(toRegist)的校验方法(validateToRegist),另外,struts2也提供了内置类型转换功能(例如:传递一个非数字给age(Integer),传递非日期类型给birthday(Date)),调用顺序:内置类型转换->validateToRegist->validate->toRegist
如果未定义特地的处理方法(toRegist)将使用默认的execute方法,这时如果想要定制检验方法,可以自定义一个validateExecute方法进行检验,将validate方法空实现。
当struts2用户输入数据传递到后台进行内置类型转换时,如果转换失败,默认的提示信息如下:
这时如果我们想要定制提示信息可以在对应的Action的目录下添加一个Action类名.properties文件(RegistAction.properties)更改默认的提示信息,命名方式为:invalid.fieldvalue.检验对象=提示信息 如:invalid.fieldvalue.birthday=出生日期格式错误,因为properties文件对中文需转换为Unicode编码,所以最好使用IDE自带的properties文件编辑模式,会自动将对应的中文转换为Unicode编码。
修改默认提示信息后:
struts2中的检验错误默认两种:ActionError、FieldError。其中ActionError是Action级别的错误,FieldError是属性错误。可以通过addActionError和addFieldError添加这两类检验错误的提示信息,addFieldError有两个参数,分别是:属性名、提示信息。展示页面可以通过struts2标签<s:actionerror />显示ActionError,<s:fielderror />显示FieldError。另外,如果展示页面使用struts2的标签容纳属性输入,那么该属性的检验错误信息会默认显示在对应属性标签上。
以下是实例程序的实际运行效果:
原理解析:
ActionSupport双继承了Validateable和ValidationAware接口,validate()是Validateable接口中的方法,我们继承Validateable接口,实现validate()就可以在调用Action的execute()方法之前,执行validate()方法进行数据检验。
ActionSupport中有一个属性对象validationAware ,用于存放错误信息:
private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
public void addActionError(String anErrorMessage) {
validationAware.addActionError(anErrorMessage);
}
public void addActionMessage(String aMessage) {
validationAware.addActionMessage(aMessage);
}
public void addFieldError(String fieldName, String errorMessage) {
validationAware.addFieldError(fieldName, errorMessage);
}
而ValidationAwareSupport对象中,错误信息实际是存放在几个集合中:
private Collection<String> actionErrors;
private Collection<String> actionMessages;
private Map<String, List<String>> fieldErrors;
private Map<String, List<String>> internalGetFieldErrors() {
if (fieldErrors == null) {
fieldErrors = new LinkedHashMap<String, List<String>>();
}
return fieldErrors;
}
public synchronized void addFieldError(String fieldName, String errorMessage) {
final Map<String, List<String>> errors = internalGetFieldErrors();
List<String> thisFieldErrors = errors.get(fieldName);
if (thisFieldErrors == null) {
thisFieldErrors = new ArrayList<String>();
errors.put(fieldName, thisFieldErrors);
}
thisFieldErrors.add(errorMessage);
}
public synchronized boolean hasActionErrors() {
return (actionErrors != null) && !actionErrors.isEmpty();
}
public synchronized boolean hasFieldErrors() {
return (fieldErrors != null) && !fieldErrors.isEmpty();
}
public synchronized boolean hasErrors() {
return (hasActionErrors() || hasFieldErrors());
}