服务端的校验也是很重要的.struts提供了两种,一种是通过validate方法,一种是通过校验框架.
ActionSupport里面的validate方法就是用来作验证的,为什么他可以有这样的方法,那是因为他实现了一些接口,public class ActionSupport implements Action, Validateable,
机制:一个Action先执行validate方法然后才会再执行execute方法.struts提供的两种错误的级别Action级别的,一种是Field级别的.在struts2中,如果你的输入校验出错的话,他默认是会转到名字叫input的result的.
执行流程:
1) 首先进行类型转换
2) 然后进行输入校验(执行validate方法)
3) 如果在上述过程中出现了任何错误,都不会再去执行execute方法,会转向struts.xml中该action的名为input的result所对应的页面.
如一个典型的验证代码如下:
public void validate() {
if(null==username||username.length()<4||username.length()>6){
this.addActionError("username invalid");
this.addFieldError("username", "username field invalid");
}
if(null==password||password.length()<4||password.length()>6){
this.addActionError("password invalid");
}else if(null==repassword||repassword.length()<4||repassword.length()>6){
this.addActionError("repassword invalid");
}else if(!password.equals(repassword)){
this.addActionError("password not the same as repassword");
}
if(age<10||age>50){
this.addActionError("age invalid");
}
if(null==birthday){
this.addActionError("birthday invalid");
}
if(null==graduation){
this.addActionError("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.addActionError("birthday not before graduation");
}
}
this.getActionErrors().clear();
}
关于错误级别:struts提供的两种错误的级别Action级别的,一种是Field级别的.
Action级别的错误与Field级别的错误:通过不同的标签库来得到他们的错误消息分别为<s:actionerror>和<s:fielderror>,这两种错误的存放地方是不一样的.
ActionSupport类的addActionError()方法的实现:首先创建一个ArrayList对象,然后将错误消息添加到该ArrayList对象中。
他的底层是这样的:
public synchronized void addActionError(String anErrorMessage) {
internalGetActionErrors().add(anErrorMessage);
}
internalGetActionErrors的定义如下:
private Collection<String> internalGetActionErrors() {
if (actionErrors == null) {
actionErrors = new ArrayList<String>();
}
return actionErrors;
}
当调用getActionErrors()方法返回Action级别的错误信息列表时,返回的实际上是集合的一个副本而不是集合本身,因此对集合副本调用clear()方法清除的依旧是副本中的元素而非原集合中的元素,此时原集合中的内容没有收到任何的影响。换句话说,Action级别的错误信息列表对开发者来说是只读的。对于field级别的信息的原理也是一样的
底层代码如下: public synchronized Collection<String> getActionErrors() {
return new ArrayList<String>(internalGetActionErrors());
}
通过这样的方式把原先internalGetActionErrors()方法里面返回的那个actionErrors放到他里面去
所以如果要试图用这样的方法去清除放在list里面的错误信息而让Action转到execute方法去是行不通的,如:
this.getFieldErrors().clear();
this.getActionErrors().clear();
但是可以通过如下的方式:
this.clearActionErrors();
this.clearFieldErrors();
Field Error级别的错误信息底层是用LinkedHashMap实现的,该Map的key是String类型,value是List<String>类型,这就表示一个Field Name可以对应多条错误信息,这些错误信息都放置在List<String>集合当中。
底层代码如下:
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);
}
struts2自动提供的错误信息,发生在转换阶段而不是输入阶段的,并且是放到field级别的错误里面,这点一定要注意的.可以这样理解:Action级别的都是我们手工去放的,而field既可以手工又可以由struts来放fildeError是放在一个map里面的,而actionError是放在一个其他类型的集合里面的.
struts2提供的默认的field级别的错误信息怎么去掉?他允许我们提供自定义的Field级别的错误提示消息
自定义Field级别的错误提示消息
1) 新建一个以Action名命名的properties文件,如RegisterAction.properties。
2) 然后在该属性文件中指定每一个出错字段的错误消息
invalid.fieldvalue.birthday=birthday invalid!!注意这里的这个invalid.fieldvalue是固定的