http://www.opensymphony.com/webwork/wikidocs/J2SE%205%20Support.html
http://www.opensymphony.com/webwork/wikidocs/Validation%20Annotation.html
WEBWORK中需要加入包xwork-tiger
一般有两种注解法
1.直接注在get方法上面,像这种
@RequiredStringValidator(message="Supply password")
public String getPassword() {
return password;
}
2.注在方法上面,like
@Validations(
requiredStrings={
@RequiredStringValidator(fieldName="username",message="用户名不能为空!" key="i18n,國際化功能"),
@RequiredStringValidator(fieldName="telNum",message="电话号码不能为空!")
},
regexFields={@RegexFieldValidator(fieldName="telNum",expression="^(\\+86|0|1)\\d{10,11}$",
message="电话号码格式不正确!")}
)
package com.gumtreenet.company.action;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Timestamp;
import java.util.List;
import com.gumtreenet.company.base.Page;
import com.gumtreenet.company.service.IDdSubService;
import com.gumtreenet.company.service.IDownloadlibraryService;
import com.gumtreenet.company.vo.Downloadlibrary;
import com.gumtreenet.company.vo.Resume;
import com.opensymphony.webwork.dispatcher.json.JSONObject;
import com.opensymphony.xwork.ActionSupport;
import com.opensymphony.xwork.validator.annotations.RequiredStringValidator;
import com.opensymphony.xwork.validator.annotations.Validations;
/**
* 附件action
*
* @author 李义星
* @version 0.1
* @datetime 2011-03-22
*/
public class DownloadlibraryAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private final static String DDMAINNAME = "下载类型";
private Downloadlibrary downlib;
private IDownloadlibraryService downService;
private IDdSubService ddSubService;
private FileInputStream downIn;
private File down;
private String downFileName;
private String downContentType;
private Page page;
private JSONObject jsonObject;
private Timestamp start;
private Timestamp end;
private List<Resume> findDowns;
public Downloadlibrary getDownlib() {
return downlib;
}
public void setDownlib(Downloadlibrary downlib) {
this.downlib = downlib;
}
public IDownloadlibraryService getDownService() {
return downService;
}
public void setDownService(IDownloadlibraryService downService) {
this.downService = downService;
}
public IDdSubService getDdSubService() {
return ddSubService;
}
public void setDdSubService(IDdSubService ddSubService) {
this.ddSubService = ddSubService;
}
public FileInputStream getDownIn() {
return downIn;
}
public void setDownIn(FileInputStream downIn) {
this.downIn = downIn;
}
public File getDown() {
return down;
}
public void setDown(File down) {
this.down = down;
}
public String getDownFileName() {
return downFileName;
}
public void setDownFileName(String downFileName) {
this.downFileName = downFileName;
}
public String getDownContentType() {
return downContentType;
}
public void setDownContentType(String downContentType) {
this.downContentType = downContentType;
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
public JSONObject getJsonObject() {
return jsonObject;
}
public void setJsonObject(JSONObject jsonObject) {
this.jsonObject = jsonObject;
}
public Timestamp getStart() {
return start;
}
public void setStart(Timestamp start) {
this.start = start;
}
public Timestamp getEnd() {
return end;
}
public void setEnd(Timestamp end) {
this.end = end;
}
public List<Resume> getFindDowns() {
return findDowns;
}
public void setFindDowns(List<Resume> findDowns) {
this.findDowns = findDowns;
}
@Validations(requiredStrings = {
@RequiredStringValidator(fieldName = "downFileName", message = "请输入附件标题"),
@RequiredStringValidator(fieldName = "downFileName", message = "请输入附件") })
public String addDown() {
return SUCCESS;
}
@Validations(requiredStrings = {
@RequiredStringValidator(fieldName = "downFileName", message = "请1"),
@RequiredStringValidator(fieldName = "downFileName", message = "") })
public String deleteDown() {
return SUCCESS;
}
}
但无论是哪种注解,默认情况下都是对这个action的所有方法进行验证。
如上面的图,我虽然给deleteDown和addDown两个方法都写了对应的验证注解,但是结果是访问delete的时候,add的验证也起作用了。
在struts2中好解决
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
struts2中这个验证器是支持按方法进行区分注解的。
只要在
<!--开启方法级别的验证-->
validation的配置上加入validateAnnotatedMethodOnly,值是true
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
<param name="validateAnnotatedMethodOnly">true</param>
</interceptor-ref>
但是webwork是不支持的。
webwork默认是使用xwork1的。而xwork1的注解验证需要xwork-tiger.jar的支持。
我对其进行的跟踪。发现它构建注解验证配置的是在类com.opensymphony.xwork.validator.AnnotationValidationConfigurationBuilder的静态方法
public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(Class aClass) 从参数中可以看出来,它是不支持方法级别的验证的。
因此必须对这个类进行改进。
public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(Class aClass) {
List<ValidatorConfig> result = new ArrayList<ValidatorConfig>();
List<ValidatorConfig> temp = processAnnotations(aClass);
if (temp != null) {
result.addAll(temp);
}
Method[] methods = aClass.getDeclaredMethods();
if ( methods != null ) {
for (Method method : methods) {
temp = processAnnotations(method);
if (temp != null) {
result.addAll(temp);
}
}
}
return result;
}
它的上级调用代码(堆栈)是:
protected List<ValidatorConfig> buildClassValidatorConfigs(Class aClass, boolean checkFile) {
String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX;
List<ValidatorConfig> result = new ArrayList<ValidatorConfig>(loadFile(fileName, aClass, checkFile));
List<ValidatorConfig> annotationResult = new ArrayList<ValidatorConfig>(AnnotationValidationConfigurationBuilder.buildAnnotationClassValidatorConfigs(aClass));
result.addAll(annotationResult);
return result;
}
两部分都可以看出,它并没有把调用的实际方法传进来,因此可以知道它不支持方法级别的注解。
再往上一级调用堆栈是
private List<ValidatorConfig> buildValidatorConfigs(Class clazz, String context, boolean checkFile, Set checked) {
List<ValidatorConfig> validatorConfigs = new ArrayList<ValidatorConfig>();
if (checked == null) {
checked = new TreeSet<String>();
} else if (checked.contains(clazz.getName())) {
return validatorConfigs;
}
if (clazz.isInterface()) {
Class[] interfaces = clazz.getInterfaces();
for (Class anInterface : interfaces) {
validatorConfigs.addAll(buildValidatorConfigs(anInterface, context, checkFile, checked));
}
} else {
if (!clazz.equals(Object.class)) {
validatorConfigs.addAll(buildValidatorConfigs(clazz.getSuperclass(), context, checkFile, checked));
}
}
// look for validators for implemented interfaces
Class[] interfaces = clazz.getInterfaces();
for (Class anInterface1 : interfaces) {
if (checked.contains(anInterface1.getName())) {
continue;
}
validatorConfigs.addAll(buildClassValidatorConfigs(anInterface1, checkFile));
if (context != null) {
validatorConfigs.addAll(buildAliasValidatorConfigs(anInterface1, context, checkFile));
}
checked.add(anInterface1.getName());
}
validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile));
if (context != null) {
validatorConfigs.addAll(buildAliasValidatorConfigs(clazz, context, checkFile));
}
checked.add(clazz.getName());
return validatorConfigs;
}
这里的参数context就是方法名。
validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile));
这个方法是针对全局的验证配置加载
validatorConfigs.addAll(buildAliasValidatorConfigs(clazz, context, checkFile));这个是针对方法级别的配置加载,但是不支持注解。
由于http://www.opensymphony.com/webwork/wikidocs/J2SE%205%20Support.html
http://www.opensymphony.com/webwork/wikidocs/Validation%20Annotation.html
WEBWORK中需要加入包xwork-tiger
一般有两种注解法
1.直接注在get方法上面,像这种
@RequiredStringValidator(message="Supply password")
public String getPassword() {
return password;
}
2.注在方法上面,like
@Validations(
requiredStrings={
@RequiredStringValidator(fieldName="username",message="用户名不能为空!" key="i18n,國際化功能"),
@RequiredStringValidator(fieldName="telNum",message="电话号码不能为空!")
},
regexFields={@RegexFieldValidator(fieldName="telNum",expression="^(\\+86|0|1)\\d{10,11}$",
message="电话号码格式不正确!")}
)
package com.gumtreenet.company.action;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Timestamp;
import java.util.List;
import com.gumtreenet.company.base.Page;
import com.gumtreenet.company.service.IDdSubService;
import com.gumtreenet.company.service.IDownloadlibraryService;
import com.gumtreenet.company.vo.Downloadlibrary;
import com.gumtreenet.company.vo.Resume;
import com.opensymphony.webwork.dispatcher.json.JSONObject;
import com.opensymphony.xwork.ActionSupport;
import com.opensymphony.xwork.validator.annotations.RequiredStringValidator;
import com.opensymphony.xwork.validator.annotations.Validations;
/**
* 附件action
*
* @author 李义星
* @version 0.1
* @datetime 2011-03-22
*/
public class DownloadlibraryAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private final static String DDMAINNAME = "下载类型";
private Downloadlibrary downlib;
private IDownloadlibraryService downService;
private IDdSubService ddSubService;
private FileInputStream downIn;
private File down;
private String downFileName;
private String downContentType;
private Page page;
private JSONObject jsonObject;
private Timestamp start;
private Timestamp end;
private List<Resume> findDowns;
public Downloadlibrary getDownlib() {
return downlib;
}
public void setDownlib(Downloadlibrary downlib) {
this.downlib = downlib;
}
public IDownloadlibraryService getDownService() {
return downService;
}
public void setDownService(IDownloadlibraryService downService) {
this.downService = downService;
}
public IDdSubService getDdSubService() {
return ddSubService;
}
public void setDdSubService(IDdSubService ddSubService) {
this.ddSubService = ddSubService;
}
public FileInputStream getDownIn() {
return downIn;
}
public void setDownIn(FileInputStream downIn) {
this.downIn = downIn;
}
public File getDown() {
return down;
}
public void setDown(File down) {
this.down = down;
}
public String getDownFileName() {
return downFileName;
}
public void setDownFileName(String downFileName) {
this.downFileName = downFileName;
}
public String getDownContentType() {
return downContentType;
}
public void setDownContentType(String downContentType) {
this.downContentType = downContentType;
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
public JSONObject getJsonObject() {
return jsonObject;
}
public void setJsonObject(JSONObject jsonObject) {
this.jsonObject = jsonObject;
}
public Timestamp getStart() {
return start;
}
public void setStart(Timestamp start) {
this.start = start;
}
public Timestamp getEnd() {
return end;
}
public void setEnd(Timestamp end) {
this.end = end;
}
public List<Resume> getFindDowns() {
return findDowns;
}
public void setFindDowns(List<Resume> findDowns) {
this.findDowns = findDowns;
}
@Validations(requiredStrings = {
@RequiredStringValidator(fieldName = "downFileName", message = "请输入附件标题"),
@RequiredStringValidator(fieldName = "downFileName", message = "请输入附件") })
public String addDown() {
return SUCCESS;
}
@Validations(requiredStrings = {
@RequiredStringValidator(fieldName = "downFileName", message = "请1"),
@RequiredStringValidator(fieldName = "downFileName", message = "") })
public String deleteDown() {
return SUCCESS;
}
}
但无论是哪种注解,默认情况下都是对这个action的所有方法进行验证。
如上面的图,我虽然给deleteDown和addDown两个方法都写了对应的验证注解,但是结果是访问delete的时候,add的验证也起作用了。
在struts2中好解决
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
struts2中这个验证器是支持按方法进行区分注解的。
只要在
<!--开启方法级别的验证-->
validation的配置上加入validateAnnotatedMethodOnly,值是true
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
<param name="validateAnnotatedMethodOnly">true</param>
</interceptor-ref>
但是webwork是不支持的。
webwork默认是使用xwork1的。而xwork1的注解验证需要xwork-tiger.jar的支持。
我对其进行的跟踪。发现它构建注解验证配置的是在类com.opensymphony.xwork.validator.AnnotationValidationConfigurationBuilder的静态方法
public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(Class aClass) 从参数中可以看出来,它是不支持方法级别的验证的。
因此必须对这个类进行改进。
public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(Class aClass) {
List<ValidatorConfig> result = new ArrayList<ValidatorConfig>();
List<ValidatorConfig> temp = processAnnotations(aClass);
if (temp != null) {
result.addAll(temp);
}
Method[] methods = aClass.getDeclaredMethods();
if ( methods != null ) {
for (Method method : methods) {
temp = processAnnotations(method);
if (temp != null) {
result.addAll(temp);
}
}
}
return result;
}
它的上级调用代码(堆栈)是:
protected List<ValidatorConfig> buildClassValidatorConfigs(Class aClass, boolean checkFile) {
String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX;
List<ValidatorConfig> result = new ArrayList<ValidatorConfig>(loadFile(fileName, aClass, checkFile));
List<ValidatorConfig> annotationResult = new ArrayList<ValidatorConfig>(AnnotationValidationConfigurationBuilder.buildAnnotationClassValidatorConfigs(aClass));
result.addAll(annotationResult);
return result;
}
两部分都可以看出,它并没有把调用的实际方法传进来,因此可以知道它不支持方法级别的注解。
再往上一级调用堆栈是
private List<ValidatorConfig> buildValidatorConfigs(Class clazz, String context, boolean checkFile, Set checked) {
List<ValidatorConfig> validatorConfigs = new ArrayList<ValidatorConfig>();
if (checked == null) {
checked = new TreeSet<String>();
} else if (checked.contains(clazz.getName())) {
return validatorConfigs;
}
if (clazz.isInterface()) {
Class[] interfaces = clazz.getInterfaces();
for (Class anInterface : interfaces) {
validatorConfigs.addAll(buildValidatorConfigs(anInterface, context, checkFile, checked));
}
} else {
if (!clazz.equals(Object.class)) {
validatorConfigs.addAll(buildValidatorConfigs(clazz.getSuperclass(), context, checkFile, checked));
}
}
// look for validators for implemented interfaces
Class[] interfaces = clazz.getInterfaces();
for (Class anInterface1 : interfaces) {
if (checked.contains(anInterface1.getName())) {
continue;
}
validatorConfigs.addAll(buildClassValidatorConfigs(anInterface1, checkFile));
if (context != null) {
validatorConfigs.addAll(buildAliasValidatorConfigs(anInterface1, context, checkFile));
}
checked.add(anInterface1.getName());
}
validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile));
if (context != null) {
validatorConfigs.addAll(buildAliasValidatorConfigs(clazz, context, checkFile));
}
checked.add(clazz.getName());
return validatorConfigs;
}
这里的参数context就是方法名。
validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile));这部会把整个类的方法的注解也加入配置集合中。基本上没找到可以入手的地方。
注解,既然它是针对注解的,那我就再写一个注解。
解压出xwork-tiger.jar包的源码。
添加注解类
package com.opensymphony.xwork.validator.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定义方法级别的注解配置
*
* @author ANSHU87
*
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodValidation {
}
这个注解类只能写在class上面。
添加类
package com.opensymphony.xwork.validator;
import java.lang.annotation.Annotation;
public class ConfigState {
private boolean methodValidation = false; //是否开启方法注解
private Annotation[] annotations; //类的注解信息
public boolean isMethodValidation() {
return methodValidation;
}
public void setMethodValidation(boolean methodValidation) {
this.methodValidation = methodValidation;
}
public Annotation[] getAnnotations() {
return annotations;
}
public void setAnnotations(Annotation[] annotations) {
this.annotations = annotations;
}
}
用于保存获取到的class注解配置信息。
修改源码包的类
AnnotationValidationConfigurationBuilder
private static List<ValidatorConfig> processAnnotations(Object o) 方法修改如下
@SuppressWarnings("unchecked")
private static List<ValidatorConfig> processAnnotations(Object o,
String context, ConfigState configState) {
List<ValidatorConfig> result = new ArrayList<ValidatorConfig>();
String fieldName = null;
Annotation[] annotations = null;
if (o instanceof Class) {
Class clazz = (Class) o;
annotations = clazz.getAnnotations();
configState.setAnnotations(annotations);
}
if (o instanceof Method) {
Method method = (Method) o;
// 开启了方法级别验证
if (configState.isMethodValidation()) {
if(context != null && !context.equals("")){
if (!context.equals(method.getName())) {
return result;
}
}
}
fieldName = resolvePropertyName(method);
annotations = method.getAnnotations();
}
if (annotations != null) {
for (Annotation a : annotations) {
// Process collection of custom validations
if (a instanceof Validations) {
processValidationAnnotation(a, fieldName, result);
}
// Process single custom validator
if (a instanceof Validation) {
Validation v = (Validation) a;
if (v.validations() != null) {
for (Validations val : v.validations()) {
processValidationAnnotation(val, fieldName, result);
}
}
}
// Process single custom validator
else if (a instanceof ExpressionValidator) {
ExpressionValidator v = (ExpressionValidator) a;
ValidatorConfig temp = processExpressionValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process single custom validator
else if (a instanceof CustomValidator) {
CustomValidator v = (CustomValidator) a;
ValidatorConfig temp = processCustomValidatorAnnotation(v,
fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process ConversionErrorFieldValidator
else if (a instanceof ConversionErrorFieldValidator) {
ConversionErrorFieldValidator v = (ConversionErrorFieldValidator) a;
ValidatorConfig temp = processConversionErrorFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process DateRangeFieldValidator
else if (a instanceof DateRangeFieldValidator) {
DateRangeFieldValidator v = (DateRangeFieldValidator) a;
ValidatorConfig temp = processDateRangeFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process EmailValidator
else if (a instanceof EmailValidator) {
EmailValidator v = (EmailValidator) a;
ValidatorConfig temp = processEmailValidatorAnnotation(v,
fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process FieldExpressionValidator
else if (a instanceof FieldExpressionValidator) {
FieldExpressionValidator v = (FieldExpressionValidator) a;
ValidatorConfig temp = processFieldExpressionValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process IntRangeFieldValidator
else if (a instanceof IntRangeFieldValidator) {
IntRangeFieldValidator v = (IntRangeFieldValidator) a;
ValidatorConfig temp = processIntRangeFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process DoubleRangeFieldValidator
else if (a instanceof DoubleRangeFieldValidator) {
DoubleRangeFieldValidator v = (DoubleRangeFieldValidator) a;
ValidatorConfig temp = processDoubleRangeFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process RequiredFieldValidator
else if (a instanceof RequiredFieldValidator) {
RequiredFieldValidator v = (RequiredFieldValidator) a;
ValidatorConfig temp = processRequiredFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process RequiredStringValidator
else if (a instanceof RequiredStringValidator) {
RequiredStringValidator v = (RequiredStringValidator) a;
ValidatorConfig temp = processRequiredStringValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process StringLengthFieldValidator
else if (a instanceof StringLengthFieldValidator) {
StringLengthFieldValidator v = (StringLengthFieldValidator) a;
ValidatorConfig temp = processStringLengthFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process UrlValidator
else if (a instanceof UrlValidator) {
UrlValidator v = (UrlValidator) a;
ValidatorConfig temp = processUrlValidatorAnnotation(v,
fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process VisitorFieldValidator
else if (a instanceof VisitorFieldValidator) {
VisitorFieldValidator v = (VisitorFieldValidator) a;
ValidatorConfig temp = processVisitorFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process RegexFieldValidator
else if (a instanceof RegexFieldValidator) {
RegexFieldValidator v = (RegexFieldValidator) a;
ValidatorConfig temp = processRegexFieldValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// Process StringRegexValidator
else if (a instanceof StringRegexValidator) {
StringRegexValidator v = (StringRegexValidator) a;
ValidatorConfig temp = processStringRegexValidatorAnnotation(
v, fieldName);
if (temp != null) {
result.add(temp);
}
}
// 判断是否开启了方法级别
else if (a instanceof MethodValidation) {
configState.setMethodValidation(true);
}
}
}
return result;
}
public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(
Class aClass)方法修改如下
@SuppressWarnings("unchecked")
//添加context方法,存放调用的上下文
public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(
Class aClass, String context) {
List<ValidatorConfig> result = new ArrayList<ValidatorConfig>();
ConfigState configState = new ConfigState(); //保存配置信息
List<ValidatorConfig> temp = processAnnotations(aClass, context,
configState);
if (temp != null) {
result.addAll(temp);
}
Method[] methods = aClass.getDeclaredMethods();
if (methods != null) {
for (Method method : methods) {
temp = processAnnotations(method, context, configState);
if (temp != null) {
result.addAll(temp);
}
}
}
return result;
}
修改源码包的
AnnotationActionValidatorManager类,把所有调用public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(
Class aClass)方法的代码,改成调用新的方法,public static List<ValidatorConfig> buildAnnotationClassValidatorConfigs(
Class aClass, String context)。
测试
刚才的action 在class前面添加注解
@MethodValidation
public class DownloadlibraryAction extends ActionSupport
4个文件代码
http://dl.iteye.com/topics/download/4142f2ff-2d36-3c9e-a004-ba35d3d0e275
注解验证
猜你喜欢
转载自liyixing1.iteye.com/blog/1020314
今日推荐
周排行