Springboot中的Validation参数校验详解
Springboot 参数校验
Springboot项目中,引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
基本的使用网上有很多教程,就不介绍了。
关于使用
- 校验@RequestParam、@PathVariable等,只需在controller类上加@Validated注解
- 校验JavaBean,在controlle上注解@Validated且在参数前加@Validated
下面以该类为例
@Data public class TestParam { /** * insert时要求为null */ @Null(groups = Insert.class) /** * update时要求不为空 */ @NotEmpty(groups = Update.class) private List<@NotNull Long> ids; @EnumValue(value = Gender.class) private String gender; @Valid private List<@NotNull Pet> pets; /** * 默认分组为default,若不继承 * Validated指定分组后,非指定分组将失效 */ public interface Insert extends Default { } public interface Update extends Default { } } @Data public class Pet { @Size(min = 1, max = 5) private String name; }
分组校验
分组校验有点类似Jackson序列化的JsonView,不同的情况下采取不同的策略,例如,注册时账户名必须在数据库中唯一,而登录时账户必须在数据库中存在,这个时候就需要为校验设置分组了。 情况一
@PostMapping("/insert") public TestParam insert(@RequestBody @Validated(TestParam.Insert.class) TestParam param) { return param; }
情况二
@PostMapping("/update") public TestParam update(@RequestBody @Validated(TestParam.Update.class) TestParam param) { return param; }
自定义校验
如下为自定义枚举值校验,用于解决属性定义不是enum类型,但想约束其值为枚举类型,例如上面的gender,假如定义为Gender,那么默认只能MALE或者FEMALE,想要男、女也通过校验,可以使用该注解
@Target({FIELD, PARAMETER}) @Retention(RUNTIME) @Documented @Constraint(validatedBy = {EnumValidator.class}) public @interface EnumValue { String message() default "错误的枚举值"; EnumValidateBy by() default EnumValidateBy.TOSTRING; Class<? extends Enum<?>> targetEnum(); Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } public enum EnumValidateBy { /** * 使用枚举类的哪个值校验 * 如MAEL("男"), FEMALE("女") * NAME 值必须为MAEL或者FEMALE * TOSTRING 重写toString方法返回男或者女, 值必须为男或者女 * BOTH 以上值均可 */ BOTH, NAME, TOSTRING }
实现ConstraintValidator接口校验
public class EnumValidator implements ConstraintValidator<EnumValue, String> { private final Set<String> set = new HashSet<>(8); @Override public void initialize(EnumValue constraintAnnotation) { Class<? extends Enum<?>> enumCls = constraintAnnotation.targetEnum(); EnumValidateBy by = constraintAnnotation.by(); Enum<?>[] constants = enumCls.getEnumConstants(); if (by == EnumValidateBy.NAME) { set.addAll(Arrays.stream(constants).map(Enum::name).collect(Collectors.toSet())); } else if (by == EnumValidateBy.TOSTRING) { set.addAll(Arrays.stream(constants).map(Enum::toString).collect(Collectors.toSet())); } else { set.addAll(Arrays.stream(constants).map(Enum::name).collect(Collectors.toSet())); set.addAll(Arrays.stream(constants).map(Enum::toString).collect(Collectors.toSet())); } } @Override public boolean isValid(String value, ConstraintValidatorContext context) { return set.contains(value); } }
null不在set中,校验不通过
集合元素校验
基本类型
直接在泛型参数上加上需要的注解即可
JavaBean类型
- 如仅对整个JavaBean进行校验,例如@NotNull注解,直接将注解写在泛型参数即可
- 如需对集合中每个JavaBean的属性进行校验,还需加上@Valid注解,如上面的pets
快速失败模式
hibernate官网的配置如下:
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) .configure() .addProperty( "hibernate.validator.fail_fast", "true" ) .buildValidatorFactory(); Validator validator = validatorFactory.getValidator();
只要往容器中注入Validator对象就行了。 因为spring自动配置好了,但没有开启快速失败模式,最后,参照Springboot自动配置的ValidationAutoConfiguration,只添加了快速失败部分,其余未做改动。
@Configuration public class ValidationConfig { @Bean public Validator validatorFactory(ApplicationContext context) { LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean() { @Override protected void postProcessConfiguration(javax.validation.Configuration<?> configuration) { configuration.addProperty("hibernate.validator.fail_fast", "true"); } }; MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory(context); factoryBean.setMessageInterpolator(interpolatorFactory.getObject()); return factoryBean; } }
总结
Springboot 参数校验是一种有效的验证机制,可以避免常见的错误,并提高程序的健壮性和稳定性。它的实现方式基于Java Bean验证框架,通过添加注解的方式,对属性值进行校验。开发者只需要在程序中加入相关注解即可完成参数的校验,从而提高了程序的开发效率和稳定性。
- 在controller层使用
- 分组时记得继承Default接口
- 集合嵌套校验
- 快速失败模式
到此这篇关于Springboot中的Validation参数校验详解的文章就介绍到这了,更多相关Validation参数校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
java中利用List的subList方法实现对List分页(简单易学)
本篇文章主要介绍了java中list数据拆分为sublist实现页面分页的简单代码,具有一定的参考价值,有需要的可以了解一下。2016-11-11
最新评论