JavaBean参数校验
一、 JSR303,Hibernate Validator 等校验工具的使用,以及自定义校验注解的使用
1.1 JSR303校验标准
JSR303是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。注解如下:
1.2 Hibernate validator扩展
Hibernate validator 在JSR303的基础上对校验注解进行了扩展,扩展注解如下:
Spring validtor 同样扩展了jsr303,并实现了方法参数和返回值的校验
Spring 提供了MethodValidationPostProcessor类,用于对方法的校验
1.3 @NotEmpty,@NotNull和@NotBlank的区别
1.3.1 @NotEmpty :不能为null,且Size>0
1.3.2 @NotNull:不能为null,但可以为empty,没有Size的约束
1.3.3 @NotBlank:只用于String,不能为null且trim()之后size>0
二、基础校验类型
2.1 在pom.xml中添加如下依赖
<!--jsr 303--><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>
2.2 校验工具类
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;/*** javabeanValidator*/
public class ValidatorUtils {private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();public static <T> Map<String, String> validate(T obj) {Map<String, StringBuilder> errorMap = new HashMap<>();Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class);if (set != null && set.size() > 0) {String property = null;for (ConstraintViolation<T> cv : set) {//这里循环获取错误信息,可以自定义格式property = cv.getPropertyPath().toString();if (errorMap.get(property) != null) {errorMap.get(property).append("," + cv.getMessage());} else {StringBuilder sb = new StringBuilder();sb.append(cv.getMessage());errorMap.put(property, sb);}}}return errorMap.entrySet().stream().collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue().toString()));}
}
2.3 demo
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Map;/*** @describe:* @date 2025/9/30*/
public class ValidatorDemo {@Datapublic static class User{@NotNullprivate Integer userId;@NotEmptyprivate String username;}public static void main(String[] args) {User user = new User();Map<String,String> msg = ValidatorUtils.validate(user);System.out.println(msg);}
}
三、自定义校验规则(Validator)
3.1 自定义注解
import javax.validation.Constraint;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Documented
@Constraint(validatedBy = {NotEmptyValidator.class})
public @interface NotEmpty {
}
3.2 自定义校验器
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import org.apache.commons.lang3.StringUtils;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;/*** @describe:* @date 2025/9/30*/
public class NotEmptyValidator implements ConstraintValidator<NotEmpty, Object> {@Overridepublic void initialize(NotEmpty constraintAnnotation) {}@Overridepublic boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {if(ObjectUtil.isNull(value)){return false;}if (value instanceof String) {return StringUtils.isNotEmpty(value.toString());} else if (value instanceof Collection) {return !org.springframework.util.CollectionUtils.isEmpty((Collection) value);} else if (value instanceof Map) {return CollectionUtil.isNotEmpty((Map) value);} else if (value.getClass().isArray()) {return Array.getLength(value) > 0;}return false;}
}
3.3 demo
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Map;/*** @author * @describe:* @date 2025/9/30*/
public class ValidatorDemo {@Datapublic static class User{@NotNullprivate Integer userId;@NotEmptyprivate String username;}public static void main(String[] args) {User user = new User();Map<String,String> msg = ValidatorUtils.validate(user);System.out.println(msg);}
}
四、级联校验
4.1 校验的对象中包含另一个需要校验的对象
使用@javax.validation.Valid 组合 @NotNull
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Map;/*** @author* @describe:* @date 2025/9/30*/
public class ValidatorDemo {@Datapublic static class User{@NotNullprivate Integer userId;private String username;
//如果Dept为null,则无法校验,Dept.id,需要@NotNull组合@Valid@NotNullprivate Dept dept;}@Datapublic static class Dept{@NotNullprivate Integer id;private String name;}public static void main(String[] args) {User user = new User();user.setUserId(1);
// user.setDept(new Dept()); //如果Dept为null,则无法校验,Dept.id,需要@NotNull组合Map<String,String> msg = ValidatorUtils.validate(user);System.out.println(msg);}
}
五、分组校验(Validator)
5.1 工具类
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;/*** @author * @describe:* @date 2025/9/30*/
public class ValidatorUtils {private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();/*** 简单校验* @param obj* @return* @param <T>*/public static <T> Map<String, String> validate(T obj) {Set<ConstraintViolation<T>> set = validator.validate(obj, javax.validation.groups.Default.class);return convertErrorMap(set);}/*** 分组校验* @param obj* @param groups* @return* @param <T>*/public static <T> Map<String, String> validate(T obj, Class<?>... groups) {Set<ConstraintViolation<T>> set = validator.validate(obj, groups);return convertErrorMap(set);}private static <T> Map<String, String> convertErrorMap(Set<ConstraintViolation<T>> set) {Map<String, StringBuilder> errorMap = new HashMap<>();if (set != null && set.size() > 0) {String property = null;for (ConstraintViolation<T> cv : set) {//这里循环获取错误信息,可以自定义格式property = cv.getPropertyPath().toString();if (errorMap.get(property) != null) {errorMap.get(property).append("," + cv.getMessage());} else {StringBuilder sb = new StringBuilder();sb.append(cv.getMessage());errorMap.put(property, sb);}}}return errorMap.entrySet().stream().collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue().toString()));}}
六、 Spring validator 方法级别的校验
JSR和Hibernate validator的校验只能对Object的属性进行校验,不能对单个的参数进行校验,spring 在此基础上进行了扩展,添加了MethodValidationPostProcessor拦截器,可以实现对方法参数的校验,实现如下:
6.1 实例化MethodValidationPostProcessor
@Beanpublic MethodValidationPostProcessor methodValidationPostProcessor() {return new MethodValidationPostProcessor();}
6.2 在所要实现方法参数校验的类上面添加@Validated,如下
@RestController
@Validated
public class ValidateController {
}
6.3 在方法上面添加校验规则:
@RequestMapping(value = "/test", method = RequestMethod.GET)public String paramCheck(@Length(min = 10) @RequestParam String name) {System.out.println(name);return null;}
参考:
相关链接资料
Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC https://my.oschina.net/qjx1208/blog/200946
Java Bean Validation 最佳实践 http://www.cnblogs.com/beiyan/p/5946345.html
https://www.cnblogs.com/zhuhui-site/p/10088417.html