SpringBoot系列之自定义枚举类的数据校验注解
Posted smileNicky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot系列之自定义枚举类的数据校验注解相关的知识,希望对你有一定的参考价值。
SpringBoot系列之自定义枚举类的数据校验注解
业务场景:数据校验,需要对枚举类型的数据传参,进行数据校验,不能随便传参。拓展,支持多个参数的枚举数据校验
在网上找到很多参考资料,所以本博客基于这些博客进行拓展补充,ok,先建一个springboot项目
项目环境:
- JDK 1.8
- SpringBoot2.2.1
- Maven 3.2+
- 开发工具
- IntelliJ IDEA
- smartGit
创建一个SpringBoot Initialize项目
选择jdk8
选择lombok和spring web
项目建好之后,在maven配置文件加上:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
这里可以先写个例子进行验证,写个枚举类,表示多种支付类型,比如支付宝执法,微信支付等等
package com.example.common.util.validator.sample.enums;
public enum PayTypeEnum
Cash("1","现金"),
Alipay("2","支付宝"),
WeChatPay("3","微信支付"),
BankCard("4","银行卡支付"),
CreditCard("5","信用卡支付");
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<EnumValueValidator , Object>
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
以上是关于SpringBoot系列之自定义枚举类的数据校验注解的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud系列之自定义GatewayFilterFactory