关键词:
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
springcloud系列之自定义gatewayfilterfactory(代码片段)
SpringCloud系列之自定义GatewayFilterFactory学习目的:知道创建一个网关sample知道网关的基本配置知道自定义GatewayFilterFactory类环境准备:JDK1.8SpringBoot2.2.3SpringCloud(Hoxton.SR7)Maven3.2+开发工具IntelliJIDEAsmartGit新增SpringBootInitializer项目:N 查看详情
springboot系列springboot全局异常处理数据校验(代码片段)
五、SpringBoot全局异常处理、数据校验5.1SpringBoot异常处理5.1.1Controller层局部异常处理5.1.2基于@ControllerAdvice注解的Controller层的全局异常处理5.1.3HandlerExceptionResolver处理异常解析器5.2SpringBoot数据校验5.1SpringBoot异常处理我们知道在... 查看详情
springboot之自定义查询query
下面讲解下SpringBoot之自定义查询Query的实例SpringBoot之自定义查询Query有HQL语句查询(Hibernate),还可以采用sql语句本地查询BookDao类查询接口1packagecom.hik.dao;23importjava.util.List;45importorg.springframework.data.jpa.repository.J 查看详情
重学springboot系列之统一全局异常处理(代码片段)
重学SpringBoot系列之统一全局异常处理设计一个优秀的异常处理机制异常处理的乱象例举该如何设计异常处理开发规范自定义异常和相关数据结构该如何设计数据结构枚举异常的类型自定义异常请求接口统一响应数据结构使用示... 查看详情
mybatis扩展之自定义类型处理器处理枚举类型
全局配置:<typeHandlers><typeHandlerhandler="com.gong.mybatis.typeHandler.MyEnumEmpStatusTypeHandler"javaType="com.gong.mybatis.bean.EmpStatus"/><!--<typeHandlerhandler="org.apache.ibatis 查看详情
springboot之自定义starter
1、创建一个EmptyProject2、在该工程中点击+,选择newmodule,新建一个maven工程点击确定。3、在该工程中点击+,选择newmodule,新建一个SpringInitializr工程 后面直接默认next,然后点击finishi。两个都创建完毕之后点击apply,点击OK。... 查看详情
springcloud系列之自定义gatewayfilterfactory(代码片段)
...本配置知道自定义GatewayFilterFactory类环境准备:JDK1.8SpringBoot2.2.3SpringCloud(Hoxton.SR7)Maven3.2+开发工具IntelliJIDEAsmartGit新增SpringBootInitializer项目:NewModule->SpringInitializer,选择jdk版本,至少jdk8packaging选择jar,javav... 查看详情
c语言之自定义类型(代码片段)
文章目录前言一、结构体1、结构体类型的声明2、结构体的自引用3、结构体变量的定义和初始化4、结构体内存对齐5、结构体传参二、位段1、位段的定义2、位段的内存分配3、位段的应用三、枚举1、枚举类型的定义2、枚举的优... 查看详情
saltstack学习系列之自定义grains
Master端打开存放自定义grains的目录vim/etc/salt/masterfile_roots:base:-/srv/salt/建立自定义模块cd/srv/saltmkdir_grainscd_grains编写自定义grainscatdisk.pyimportosdefdisk():grains={}disk=os.popen(‘fdisk-l|grep‘Disk‘|grep-v‘ 查看详情
springboot整合springsecurity之自定义退出(代码片段)
一security默认的退出Springsecurity默认实现了logout退出,访问/logout: 实现逻辑:点击“LogOut”退出成功。退出后访问其它url判断是否成功退出。二自定义退出2.1配置文件中配置在WebSecurityConfifig的protectedvoidconfifigure(HttpSe... 查看详情
cas5.3.1系列之自定义jdbc认证策略
CAS5.3.1系列之自定义JDBC认证策略(三)CAS官方文档是介绍基于配置实现jdbc认证的,可以参考我博客:CAS5.3.1系列之支持JDBC认证登录(二),不过我们也可以通过自定义认证策略的方式实现jdbc认证,pom先加入相关jar<!--CustomAuthen... 查看详情
flask之自定义模型类(代码片段)
4.3自定义模型类定义模型模型表示程序使用的数据实体,在Flask-SQLAlchemy中,模型一般是Python类,继承自db.Model,db是SQLAlchemy类的实例,代表程序使用的数据库。类中的属性对应数据库表中的列。id为主键,是由Flask-SQLAlchemy管理。... 查看详情
springboot之自定义场景启动器(代码片段)
1.场景启动器SpringBoot的自动配置原理中不可或缺的就是那些已经定义好的场景启动器,只要导入某个场景启动器我们的应用就拥有了该场景下的一些核心Bean,有利于快速开发,比如引入Web的场景启动器:<dependen... 查看详情
springboot2系列教程(十五)|服务端参数校验之一
估计很多朋友都认为参数校验是客户端的职责,不关服务端的事。其实这是错误的,学过Web安全的都知道,客户端的验证只是第一道关卡。它的参数验证并不是安全的,一旦被有心人抓到可乘之机,他就可以有各种方法来摸拟系... 查看详情
springboot整合springsecurity之自定义认证(代码片段)
一自定义认证页面1.1说明1.如果用户没有自定义登录页面,springsecurity默认会启动自身内部的登录页面,尽管自动生成的登录页面很方便快速启动和运行,但大多数应用程序都希望定义自己的登录页面。1.2自定义登录... 查看详情
玩转springboot原理篇(自动装配前凑之自定义stater)(代码片段)
的pom文件中可以看出,mybatis-spring-boot-starter包会自动引入mybatis-spring-boot-autoconfigure以及mybatis相关依赖包。SqlSessionFactoryExceptionlogger.debug(encoding=xmlns:xsi=xsi:schemaLocation=<modelVersion><groupI 查看详情
springboot系列之对excel报表的校验提示
最近在做一个一对多excel类型的报表,如果excel报表数据填错了,要对其进行校验,然后返回给前端,做一个表格显示错误信息,excel报表数据读取的可以参考我上篇博客,链接Excel格式类似于,维度是... 查看详情
微信小程序之自定义模态弹窗(带动画)实例
...工具的快捷键微信小程序的文件结构——微信小程序教程系列(1)微信小程序的生命周期实例演示——微信小程序教程系列(2)微信小程序的动态修改视图层的数据——微信小程序教程系列(3)微信小程序的新建页面——微信... 查看详情