JAVA && Spring && SpringBoot2.x — 学习目录
后台如何对参数进行校验?比如参数不能为null,email那么必须符合email的格式,如果手动进行if判断或者写正则表达式判断无疑发效率太慢。那么有没有现成的框架让我们使用呢?
1. validation bean介绍
1.1 什么叫做validation bean
validation bean是基于JSR-303标准开发出来的,使用注解方式实现,及其方便。是这只是一个接口,没有具体实现.Hibernate Validator是一个hibernate独立的包,可以直接引用,他实现了validation bean同时有做了扩展,比较强大 ,实现图如下:
1.2 注解
- @NotEmpty 用在
集合
和String
上面; - @NotBlank用在
String
上面; - @NotNull可以用在自定义对象上;
class Item {
@Digits(integer = 6, fraction = 2, message = "{javax.validation.constraints.Digits.message}")
private BigDecimal amount;
}
其中integer和fraction是强制的,并且消息是可选参数。
正则表达式中,如何允许【空格】或者【空串】
public class User {
@Pattern(regexp = "(^0|1|[ ]+$)|(^$)|",message = "信息不符")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
[ ]+表示允许一个或者多个空格,而^$表示是空串。
1.3 验证方法
maven依赖
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<!-- hibernate validator-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.0.Final</version>
</dependency>
核心方法-验证
public class ValidateUtil {
private static Validator validator; // thread-safe
static {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
public static <T> void validate(T t) throws ValidateException {
if (null == t) {
throw new ValidateException("300", "验证数据不能为空");
}
List<String> errorList = new ArrayList<String>();
Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
for (ConstraintViolation<T> constraintViolation : constraintViolations) {
errorList.add(constraintViolation.getMessage());
}
if ((null != errorList) && !errorList.isEmpty()) {
throw new ValidateException("301", StringUtils.join(errorList, ","));
}
}
}
测试方法
public static void main(String[] args) {
User user = new User();
try {
ValidateUtil.validate(user);
} catch (Exception e) {
e.printStackTrace();
}
}
需要注意的是:javax.validation.UnexpectedTypeException: No validator could be found for type: java.lang.Integer异常是由于:在写接口的时候,一般去查找类的Integer属性上加了不属于整型的校验,比如@NotEmpty,@Length,@Pattern等。
2. 自定义验证注解
1. 参数枚举
/**
* 枚举类
*/
public enum CaseMode {
UPPER,LOWER
}
2. 声明注解
此处使用@Constraint注解处理对象的逻辑。
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = CheckCaseValidator.class)
@Documented
public @interface CheckCase {
String message() default "{com.mycompany.constraints.checkcase}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
CaseMode value();
}
3. 注解逻辑
import com.creditease.eaclient.bg.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> {
private CaseMode caseMode;
//获取传入的CaseMode对象
@Override
public void initialize(CheckCase constraintAnnotation) {
this.caseMode = constraintAnnotation.value();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (StringUtils.isBlank(value)) {
return true;
}
if (caseMode == CaseMode.UPPER) {
return value.equals(value.toUpperCase());
} else {
return value.equals(value.toLowerCase());
}
}
}
4. 使用方法
public class User {
@CheckCase(value = CaseMode.UPPER, message = "name需要大写")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5. 运行结果
自定义注解逻辑处理类由于实现了ConstraintValidator接口,所以它默认被spring管理成bean,所以可以在这个逻辑处理类里面用@Autowiredu或者@Resources注入别的服务,而且不用在类上面用@Compent注解成spring的bean。
自定义验证类型注解类里面由于是用于验证数据,一般在里面加上
String message() default "用户不存在或者不属于当前组织";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};