validation实现自定义注解

java接口使用入参时经常会判断一些参数的校验规则,使用validation的标签判断能拦截大部分不符合要求的参数,如:notnull max min ...

而有些业务需求的判断也可以通过自定义的标签来实现


下面实现request入参:判断多个参数需要有至少一个不为空


pom依赖的包:

                <dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.0.2.Final</version>
		</dependency>

		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>

 


自定义标签的实现:

package com.use;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;

import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = SimultaneousNotNull.BindChecker.class)
@Documented
public @interface SimultaneousNotNull {
  //该组检查不为空的参数共有几个
  int checkCount();

  String message() default "参数不能同时为空!";

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};


  public static class BindChecker implements ConstraintValidator<SimultaneousNotNull, String> {

    private static final ReentrantLock LOCK = new ReentrantLock();
    
    //全局统计打标签SimultaneousNotNull 的个数,用来跟checkCount判断是否可做最后一个判断
    private static AtomicInteger atomicInteger = new AtomicInteger(0);
    
    //标记打标签SimultaneousNotNull是否有一个入参有值,只要一个有值置为true,即满足条件
    private static AtomicBoolean atomicBoolean = new AtomicBoolean(false);

    /**
     * @see javax.validation.ConstraintValidator#initialize(java.lang.annotation.Annotation)
     */
    public void initialize(SimultaneousNotNull constraintAnnotation) {}

    /**
     * @see javax.validation.ConstraintValidator#isValid(java.lang.Object,
     *      javax.validation.ConstraintValidatorContext)
     */
    public boolean isValid(String strValue, ConstraintValidatorContext context) {
      atomicInteger.getAndIncrement();
      Map<String, Object> attributes =
          ((ConstraintValidatorContextImpl) context).getConstraintDescriptor().getAttributes();
      String type = (String) attributes.get("type");
      String message = (String) attributes.get("message");
      int checkCount = Integer.parseInt(attributes.get("checkCount").toString());
      
      //同步加锁
      LOCK.lock();
      try {
        if (StringUtils.isNotBlank(strValue)) {
          atomicBoolean.set(true);
        }
        //last one
        if (atomicInteger.get() == checkCount && !atomicBoolean.get()) {
          return false;
        }
        return true;
      } finally {
        if (atomicInteger.get() == checkCount) {
          atomicBoolean.set(false);
          atomicInteger.set(0);
        }
        // 释放锁
        LOCK.unlock();
      }
    }


  }

}

 

request校验的实体

package com.use;

import javax.validation.constraints.NotNull;

public class BindCase{

  @SimultaneousNotNull(checkCount = 2)
  private String customer;
  
  @SimultaneousNotNull(checkCount = 2)
  private String id;
  
  @NotNull
  private String name;

  public String getCustomer() {
    return customer;
  }

  public void setCustomer(String customer) {
    this.customer = customer;
  }

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  
  
}

 

main方法

package com.use;

import java.util.Iterator;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.groups.Default;
public class Main {
  
  public static void main(String[] args) {
    BindCase case1 = new BindCase();
//    case1.setCustomer("1");

  Set<ConstraintViolation<BindCase>> constraintViolations =
      Validation.buildDefaultValidatorFactory().getValidator().validate(case1, Default.class);
  if (!constraintViolations.isEmpty()) {
      Iterator<ConstraintViolation<BindCase>> it = constraintViolations.iterator();
      StringBuilder sb = new StringBuilder();
      String msg;
      while (it.hasNext()) {
          sb.append(it.next().getMessage());
          sb.append(",");
      }
      msg = sb.substring(0, sb.lastIndexOf(",")).toString();
      System.err.println(msg);
      System.err.println("校验结束");
  }
  }
  

}

 

以上的业务逻辑实现主要是实现了javax.validation.ConstraintValidatorContext接口

如果有其它需求也可以参考实现自定义的校验标签

 

猜你喜欢

转载自ttkx1988.iteye.com/blog/2358608