1. 简介
在java开发中,经常见到许多通过注解@Annotation实现功能的优秀代码,尤其在接触spring之后,对注解更是一发不可收拾,这里将向读者介绍一种范围定界方法。需要说明的是,这种定界方法不能独立于世,而必须结合Validation-api-*.jar公共包一起使用。这里以定界一个变量private String agentId;取值范围(1,3) 为例来说明。
2. 创建Annotation
在eclipse上选中某个指定的package,右键 new ,选择Annotation,这里创建的Annotation的名字叫做@IntRange,其代码如下
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import javax.validation.Constraint;
import javax.validation.Payload;
import com.*.constrait.validator.IntRangeValidator;
/**
*
* @author ***
* @see 用于判定指定类中的某个域是否在规定区间之内
*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = IntRangeValidator.class)
public @interface IntRange {
String message() default "{com.*.validation.constraints.IntRange.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int min() default 0;
int max() default Integer.MAX_VALUE;
}
代码中的@Target 用于指定该注解的应用范围,此注解应用于 方法、域、构造函数 、入参四个区域;@Retention指定应用时间,这里是RUNTIME;@Constraint指明具体实现的类,即IntRangeValidator.java类
代码中定义了两个函数 int min();和 int max();两个函数都有各自的默认值。
Annotation可以认为是一个接口,其中只是简单定义了要实现哪些功能,具体的实现步骤则交由其他指定的类(这里专指IntRangeValidator)去处理。
3. 具体实现
上面已经指出,@Annotation只是一个类似于接口的类,具体的实现由其他类完成,这里将介绍具体实现,代码如下:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.*.constrait.constrains.IntRange;
public class IntRangeValidator implements ConstraintValidator<IntRange, String> {
private int min;
private int max;
@Override
public void initialize(IntRange arg0) {
this.min = arg0.min();
this.max = arg0.max();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext arg1) {
if((null == value) || 0 == value.length()) {
return false;
}
try {
int integer = Integer.valueOf(value);
//System.out.println("++++++ the value is " + integer+ " +++++++");
return (integer > this.min) && (integer < this.max);
}catch(NumberFormatException e) {
//System.out.println("---there is a exception , " + e.toString());
return false;
}
}
}
该函数实现了ConstraintValidator接口,该接口为泛型接口,第一个参数IntRange为上文中的Annotation,其他代码也比较容易理解,此处不做介绍。
4.使用方法
假设定义了一个类Mytest01,其中有一个变量private String agentId;,则注解的方式如下
public class BasicInfo {
}
public class Mytest01 extends{
@IntRange(min=1,max=3)
private String agentId;
}
代码@IntRange()中的min和max分别调用了@IntRange中的两个函数。
该注解一般应用于对外接口,和@RequestBody、@Valid、@BindingResult一起使用,代码如下
import javax.validation.Valid;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value="/cct")
public class CcgmsController {
@PostConstruct
public void init() {
System.out.println("----------------------------------");
}
@RequestMapping(value="/agent", headers = "Accept=application/json", method = RequestMethod.POST)
public @ResponseBody ResultInfo agentAction(@RequestBody @Valid Mytest01
mytest,BindingResult result, HttpServletRequest request) {
if(result.hasErrors()) {
List<FieldError> list = result.getFieldErrors();
for(FieldError error:list) {
System.out.println(error.getObjectName()+"." + error.getField() + " failed; cause by : "+ error.getDefaultMessage());
}
}
System.out.println("++++++++++++++++++++++++++++");
return new ResultInfo("0");
}
}
public class ResultInfo {
private String result;
ResultInfo(){
}
public ResultInfo(String result){
this.result = result;
}
..........//省略get/set方法
}
当mytest入参有问题时,则将执行如下代码 if(result.hasErrors){}
上述使用是结合BindingResult的,而实际使用中又不一定会用到它,如果项目中不用BindingResult,那又应该如何实现呢? 其实Validate已经提供了类似的方法,代码如下,在使用的地方显式的调用一下Validate.checkInfo() 方法来检测注解
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import com.***.BasicInfo;
public class Validate {
private static javax.validation.Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
public static boolean checkInfo(BasicInfo basicInfo) {
if(null == basicInfo) {
System.out.println("[ccgms]: basicInfo is null");
return false;
}
Set<ConstraintViolation<BasicInfo>> sets = Validate.VALIDATOR.validate(basicInfo);
if(!sets.isEmpty()) {
System.out.println("[ccgms-validate] : there is error message" );
for(ConstraintViolation<BasicInfo> set:sets) {
//参数所在类的名称
String className = set.getRootBeanClass().getSimpleName();
//参数所在类的具体域的名称
String path = set.getPropertyPath().toString();
//定义的注解中的默认message
String message = set.getMessage();
System.out.println("[className]="+className+" ;[path]=" + path+" ;[message]=" + message );
}
return false;
}
return true;
}
}