Pre
SpringBoot - 优雅的实现【自定义参数校验】高级进阶
SpringBoot - 优雅的实现【参数分组校验】高级进阶
SpringBoot - 使用Assert校验让业务代码更简洁
概述
接上文, Spring Validation 提供的注解基本上够用,但是复杂的校验,我们还是需要自己定义注解来实现自动校验。
举个例子: 实体类中的sex性别属性 , 只能输入 M 、 F 这2个枚举值
三部曲
Step1 搞自定义注解
package com.artisan.customvalidator; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * @author 小工匠 * @version 1.0 * @mark: show me the code , change the world */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Repeatable(EnumString.List.class) @Documented @Constraint(validatedBy = EnumStringValidator.class)//标明由哪个类执行校验逻辑 public @interface EnumString { String message() default "value not in enum values."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /** * @return date must in this value array */ String[] value(); /** * Defines several {@link EnumString} annotations on the same element. * * @see EnumString */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Documented @interface List { EnumString[] value(); } }
Step2 搞校验逻辑
package com.artisan.customvalidator; import lombok.extern.slf4j.Slf4j; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.Arrays; import java.util.List; /** * @author 小工匠 * @version 1.0 * @mark: show me the code , change the world */ @Slf4j public class EnumStringValidator implements ConstraintValidator<EnumString, String> { private List<String> enumStringList; @Override public void initialize(EnumString constraintAnnotation) { log.info("EnumStringValidator initialize....."); enumStringList = Arrays.asList(constraintAnnotation.value()); } @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (value == null) { return true; } return enumStringList.contains(value); } }
Step3 使用
在字段上增加注解
Step4 验证
附 int 类型的判断
package com.artisan.customvalidator; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * @author 小工匠 * @version 1.0 * @Des 扩展int枚举校验 * @mark: show me the code , change the world */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Repeatable(EnumInteger.List.class) @Documented @Constraint(validatedBy = EnumNumberValidator.class) public @interface EnumInteger { String message() default "value not in enum values."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /** * @return date must in this value array */ int[] value(); /** * Defines several {@link EnumInteger} annotations on the same element. * * @see EnumInteger */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Documented @interface List { EnumInteger[] value(); } }
package com.artisan.customvalidator; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.ArrayList; import java.util.List; /** * @author 小工匠 * @version 1.0 * @mark: show me the code , change the world */ public class EnumNumberValidator implements ConstraintValidator<EnumInteger, Number> { private List<Integer> enumStringList; @Override public void initialize(EnumInteger constraintAnnotation) { enumStringList = new ArrayList<>(); int[] values = constraintAnnotation.value(); for (int value : values) { enumStringList.add(value); } } @Override public boolean isValid(Number value, ConstraintValidatorContext context) { if (value == null) { return true; } return enumStringList.contains(value.intValue()); } }
源码
https://github.com/yangshangwei/boot2