栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot系列之自定义枚举类的数据校验注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot系列之自定义枚举类的数据校验注解

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-api
     2.0.1.Final
 

这里可以先写个例子进行验证,写个枚举类,表示多种支付类型,比如支付宝执法,微信支付等等

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> enumClass();

    String enumMethod();
    
    class Validator implements ConstraintValidator {
        private Class> 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
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/666214.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号