核心内容摘要
凌晨四点的研磨声:当极致审美遇上极客老板,这杯豆浆凭什么刷屏?
参数校验这个东西很多情况下都是比较简单的用NotNull、Size等注解就可以解决绝大多数场景但也有一些场景是这些基本注解解决不了的只能用一些其他的方式处理这样就导致参数校验变成了多层其实是不利于代码维护的。
于是乎我写了一套几乎可以满足任何场景的参数校验组件非常好用安利给大家。
GitHub地址文末获取 它解决了什么问题枚举值字段校验SpelAssert(assertTrue T(cn.sticki.enums.UserStatusEnum).getByCode(#this.userStatus) ! null , message 用户状态不合法) private Integer userStatus;多字段联合校验NotNull private Integer contentType; SpelNotNull(condition #this.contentType 1, message 语音内容不能为空) private Object audioContent; SpelNotNull(condition #this.contentType 2, message 视频内容不能为空) private Object videoContent;复杂逻辑校验调用静态方法// 中文算两个字符英文算一个字符要求总长度不超过 10 // 调用外部静态方法进行校验 SpelAssert(assertTrue T(cn.sticki.util.StringUtil).getLength(#this.userName) 10, message 用户名长度不能超过
private String userName;调用 Spring Bean需要使用 EnableSpelValidatorBeanRegistrar 开启Spring Bean支持// 这里只是简单举例实际开发中不建议这样判断用户是否存在 SpelAssert(assertTrue userService.getById(#this.userId) ! null, message 用户不存在) private Long userId;更多使用场景欢迎探索和补充 特点强大的参数校验功能几乎支持所有场景下的参数校验。
扩展自 javax.validation 包只新增不修改无缝集成到项目中。
基于 SpELSpring Expression Language 表达式支持复杂的校验逻辑。
支持调用 Spring Bean可在表达式中使用注入过的 Spring Bean。
校验时基于整个对象支持对象内字段间的校验逻辑。
支持自定义校验注解可根据业务需求自定义校验逻辑。
无需额外的异常处理校验失败时会上报到 javax.validation 的异常体系中。
简单易用使用方式几乎与 javax.validation 一致学习成本低上手快。
环境目前仅测试了 JDK8 环境理论上来说 JDK8 应该都是支持的。
快速开始添加依赖Latest Version:
0.
2-betadependency groupIdcn.sticki/groupId artifactIdspel-validator/artifactId versionLatest Version/version /dependency dependency groupIdorg.hibernate.validator/groupId artifactIdhibernate-validator/artifactId version${hibernate-validator.version}/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId version${spring-boot-starter-web.version}/version /dependency在接口参数上使用Valid或Validated注解RestController RequestMapping(/example) public class ExampleController { /** * 简单校验示例 */ PostMapping(/simple) public RespVoid simple(RequestBody Valid SimpleExampleParamVo simpleExampleParamVo) { return Resp.ok(null); } }在实体类上使用SpelValid注解同时在需要校验的字段上使用SpelNotNull等约束注解Data SpelValid public class SimpleExampleParamVo { NotNull private Boolean switchAudio; /** * 当 switchAudio 为 true 时校验 audioContentaudioContent 不能为null */ SpelNotNull(condition #this.switchAudio true, message 语音内容不能为空) private Object audioContent; }添加全局异常处理器处理校验异常RestControllerAdvice public class ControllerExceptionAdvice { ExceptionHandler({BindException.class, MethodArgumentNotValidException.class}) public RespVoid handleBindException(BindException ex) { String msg ex.getFieldErrors().stream() .map(error - error.getField() error.getDefaultMessage()) .reduce((s1, s
- s1 , s
.orElse(); return new Resp(400, msg); } }发起请求即可看到校验结果示例一SpelNotNull 校验不通过请求体{ switchAudio: true, audioContent: null }响应体{ code: 400, message: audioContent 语音内容不能为空, data: null }示例二校验通过请求体{ switchAudio: false, audioContent: null }响应体{ code: 200, message: 成功, data: null }示例三NotNull 校验不通过请求体{ switchAudio: null, audioContent: null }响应体{ code: 400, message: switchAudio 不能为null, data: null } 使用指南注意本组件的目的不是代替javax.validation的校验注解而是作为一个扩展方便某些场景下的参数校验。
能够使用javax.validation的场景就不要使用spel-validator因为spel-validator会有一定的性能损耗。
开启约束校验需要满足以下两个条件才会对带注解的元素进行校验在接口参数上使用Valid或Validated注解在实体类上使用SpelValid注解如果只满足第一个条件那么只会对带NotNull、NotEmpty、NotBlank等注解的元素进行校验。
关注公众号码猿技术专栏回复关键词1111 获取阿里内部Java性能调优手册如果只满足第二个条件那么不会对任何元素进行校验。
这是因为SpelValid注解是基于javax.validation.Constraint实现的只有在Valid或Validated注解的支持下才会生效。
而spel-validator提供的约束注解是基于SpelValid进行扫描校验的只有在SpelValid注解生效的情况下才会执行约束校验。
使用约束注解目前支持的约束注解有注解说明对标 javax.validationSpelAssert逻辑断言校验无SpelNotNull非 null 校验NotNullSpelNotEmpty集合、字符串、数组大小非空校验NotEmptySpelNotBlank字符串非空串校验NotBlankSpelNull必须为 null 校验NullSpelSize集合、字符串、数组长度校验Size每个约束注解都包含三个默认的属性message校验失败时的提示信息。
group分组条件支持 SpEL 表达式当分组条件满足时才会对带注解的元素进行校验。
condition约束开启条件支持 SpEL 表达式当 表达式为空 或 计算结果为true 时才会对带注解的元素进行校验。
调用 Spring Bean默认情况下解析器无法识别 SpEL 表达式中的 Spring Bean。
如果需要在 SpEL 表达式中调用 Spring Bean需要在启动类上添加EnableSpelValidatorBeanRegistrar注解 开启 Spring Bean 支持。
EnableSpelValidatorBeanRegistrar SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }自定义约束注解在注解上使用SpelConstraint并指定验证器。
然后给注解添加上三个固定的字段 message 、group、condition。
实现验证器自定义示例约束示例-定义约束注解自定义约束示例-实现验证器具体实现方式可以参考cn.sticki.validator.spel.SpelConstraint类。
关注公众号码猿技术专栏回复关键词1111 获取阿里内部Java性能调优手册如果你使用过javax.validation的自定义约束注解那么你会发现SpEL Validator的自定义约束注解几乎与javax.validation一致。
示例项目我也写了一个简单的示例项目但目前还不太完善只有基本的
使用方法https://github.com/stick-i/spel-validator-example最后关于性能性能上我目前还没有进行测试但代码里使用了很多的反射会有一定的损耗后面我准备多加一些缓存尽量降低性能上的影响。
一个奇怪的现象在项目中使用SpEL的时候有一个很怪异的现象我给这两个字段都标记了Language(SpEL)但是只有condition可以识别我不知道这算不算idea的bug我目前使用的idea版本是 IntelliJ IDEA
2
1 (Ultimate Edition)有懂的朋友请帮忙解答一下。
GitHub地址https://github.com/stick-i/spel-validator