SpringBoot系列之自定义枚举类的数据校验注解
业务场景:数据校验,需要对枚举类型的数据传参,进行数据校验,不能随便传参。拓展,支持多个参数的枚举数据校验
在网上找到很多参考资料,所以本博客基于这些博客进行拓展补充,ok,先建一个springboot项目
项目环境:
- JDK 1.8
- SpringBoot2.2.1
- Maven 3.2+
- 开发工具
- IntelliJ IDEA
- smartGit
创建一个SpringBoot Initialize项目
选择jdk8
选择lombok和spring web
项目建好之后,在maven配置文件加上:
javax.validation validation-api2.0.1.Final
这里可以先写个例子进行验证,写个枚举类,表示多种支付类型,比如支付宝执法,微信支付等等
package com.example.common.util.validator.sample.enums; public enum PayTypeEnum { Cash("1","现金"), Alipay("2","支付宝"), WeChatPay("3","微信支付"), BankCard("4","yhk支付"), CreditCard("5","xyk支付"); PayTypeEnum(String code , String desc) { this.code = code; this.desc = desc; } private String code; private String desc; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
因为要校验传入参数是否为枚举类里的类型,可以在PayTypeEnum类里新增一个校验方法
public static boolean isValuevalid(String value) { if(!StringUtils.isEmpty(value)){ for (PayTypeEnum enumObj : PayTypeEnum.values()) { if (enumObj.getCode().equals(value)) { return true; } } return false; } return true; }
这里是加一下自定义的元注解类,然后通过@Constraint指定具体的校验类,通过反射机制获取对应的方法,比如isValuevalid这个方法
package com.example.common.util.validator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import javax.validation.Constraint; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = EnumValuevalidator.Validator.class) public @interface EnumValuevalidator { Logger log = LoggerFactory.getLogger(EnumValuevalidator.class); String message() default "参数有误"; Class extends Enum>> enumClass(); String enumMethod(); class Validator implements ConstraintValidator{ private Class extends Enum>> enumClass; private String enumMethod; @Override public void initialize(EnumValuevalidator constraintAnnotation) { enumMethod = constraintAnnotation.enumMethod(); enumClass = constraintAnnotation.enumClass(); } @Override public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) { // 值没传的情况,直接返回true if (StringUtils.isEmpty(o)) return Boolean.TRUE; if (enumClass == null || StringUtils.isEmpty(enumMethod)) return Boolean.TRUE; Class> vclass = o.getClass(); try { // 反射机制获取具体的校验方法 Method method = enumClass.getMethod(enumMethod,vclass); if (!Boolean.TYPE.equals(method.getReturnType()) && !Boolean.class.equals(method.getReturnType())) { throw new RuntimeException("校验方法不是布尔类型!"); } if (!Modifier.isStatic(method.getModifiers())) { throw new RuntimeException("校验方法不是静态方法!"); } method.setAccessible(true); // 调用具体的方法 Boolean res = (Boolean) method.invoke(null,o); return res != null ? res : false; } catch (NoSuchMethodException e) { log.error("NoSuchMethodException:{}" ,e); throw new RuntimeException(e); } catch (IllegalAccessException e) { log.error("IllegalAccessException:{}" ,e); throw new RuntimeException(e); } catch (InvocationTargetException e) { log.error("InvocationTargetException:{}" ,e); throw new RuntimeException(e); } } } }
具体的bean类,加上@EnumValuevalidator(enumClass = PayTypeEnum.class , enumMethod = "isStrsValid" , message = "支付类型校验有误")指向具体的枚举类和校验方法
package com.example.common.util.validator.sample.model; import com.example.common.util.validator.EnumValuevalidator; import com.example.common.util.validator.sample.enums.PayTypeEnum; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; import javax.validation.constraints.NotNull; @Data @AllArgsConstructor @NoArgsConstructor @SuperBuilder(toBuilder = true) @ToString public class ShopOrder { @EnumValuevalidator(enumClass = PayTypeEnum.class , enumMethod = "isStrsValid" , message = "支付类型校验有误") @NotNull(message = "支付类型必须传") private String payType; }
加上@Validated开启校验
package com.example.common.util.validator.sample.controller; import com.example.common.util.validator.sample.model.ShopOrder; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/orders") public class SampleController { @PostMapping public String saveOrder(@Validated ShopOrder shopOrder) { return shopOrder.toString(); } }
校验出错返回:
{ "timestamp": "2021-12-16T10:01:27.801+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "EnumValuevalidator.shopOrder.payType", "EnumValuevalidator.payType", "EnumValuevalidator.java.lang.String", "EnumValuevalidator" ], "arguments": [ { "codes": [ "shopOrder.payType", "payType" ], "arguments": null, "defaultMessage": "payType", "code": "payType" }, "com.example.common.util.validator.sample.enums.PayTypeEnum", { "defaultMessage": "isStrsValid", "arguments": null, "codes": [ "isStrsValid" ] } ], "defaultMessage": "支付类型校验有误", "objectName": "shopOrder", "field": "payType", "rejectedValue": "2,111", "bindingFailure": false, "code": "EnumValuevalidator" } ], "message": "Validation failed for object='shopOrder'. Error count: 1", "path": "/api/orders" }
拓展,这里要求传payType类型,也就是支持多选的情况,参数payType=2,111,这里要修改校验方法:
public static boolean isStrsValid(String value) { if (!value.contains(",")) return isValuevalid(value); String[] arr = StringUtils.split(value , ","); for (String s : arr) { if (!isValuevalid(s)) { return false; } } return true; }
加上注解,enumMethod 改成isStrsValid
@EnumValuevalidator(enumClass = PayTypeEnum.class , enumMethod = "isStrsValid" , message = "支付类型校验有误")
调用这个接口:
http://127.0.0.1:8080/api/orders?payType=2,111
- https://www.baeldung.com/javax-validations-enums
- https://blog.csdn.net/xiaojin21cen/article/details/102622771
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)