使用 ConstraintValidator 接口及BindingResult实现注解定义参数范围

142 篇文章 1 订阅
127 篇文章 2 订阅

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;
    }
}
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值