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接口
如果有其它需求也可以参考实现自定义的校验标签