javax.validation 参数校验

本贴最后更新于 1377 天前,其中的信息可能已经时移俗易

参数校验往往让人心塞,各种判断匹配。基本的参数校验例如实体校验可以通过如下方法解决,但是因为我们的请求响应结果都是加密字符,需要解密后才能校验,所以在此的基础上增加第二段的方式,通过封装工具类的方法完成。

————————————————
版权声明:本文为 CSDN 博主「LailaiMonkey」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/h273979586/article/details/105572872
如果是 Spring 项目那么这个架构依赖会自动引用,如果是非 Spring 项目得手动引用一下依赖。本文以 Spring 项目为主:

<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.16.Final</version> <scope>compile</scope> </dependency>

这是注解包里面元素:

@AssertFalse 被注释的元素必须为 false
@AssertTrue 被注释的元素必须为 true
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Email 被注释的元素必须是电子邮箱地址
@Future 被注释的元素必须是一个将来的日期
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@NotBlank 验证注解的元素值不为空(不为 null 并去除首尾位空格)
@NotEmpty 验证注解的元素值不为 null 且不为空(字符串长度不为 0、集合大小不为 0)
@NotNull 不为 null
@Null 为 null
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) `B 限制字符长度必须在 min 到 max 之间
验证规则
在 Spring 项目中定义一个需要验证的 model 内容如下:
@Data
public class ValidatorModel {

@NotBlank(message = "姓名不能为空") private String name; @Size(min = 3, max = 6) private List<String> friendNames; @Min(value = 18, message = "年龄未满18岁") @Max(value = 60, message = "年龄必须在60岁以下") private Integer age; private String tel; @DecimalMin(value = "30", message = "金钱不能小于30") private BigDecimal money;

service 接口内容如下:
因为是 javax 的验证构架所以在没有 Spring 时候也可以进行验证,注解得写在接口上,如果写在实现类将无效!!!

//开启验证注解 @Validated public interface ValidatorService { void validator(@Valid ValidatorModel model, @NotNull String param); }

service 实现类就是正常逻辑处理这里不在演示了。

controller 内容如下:
controller 接收参数传递给 service,在 service 接口进行参数验证,如果失败将抛出异常。

@RestController public class ValidatorController { @Autowired private ValidatorService validatorService; @GetMapping public void validator() { ValidatorModel model = new ValidatorModel(); model.setName("张三"); model.setFriendNames(Arrays.asList("李四", "王五")); model.setAge(20); model.setTel("188888888881"); model.setMoney(new BigDecimal(100)); validatorService.validator(model,"也可以在参数上做验证"); } }

异常截图:
以上是 Javax Validation 校验常用方法,可以满足多数情况,但是项目中遇到的都是少数情况,例如:
添加时候需要对所有参数进行验证,更新时候只需要对某个几参数或有值的参数进行验证(分组验证)。
可不可以自定义验证规则,我要验证性别,只能是男或女(自定义验证规则)。
分组验证
添加时候需要验证 friendNames 字段,更新时候需要验证 name 字段,这时得引用分组验证,修改 ValidatorModel 如下:

@Data public class ValidatorModel { /** * 添加分组 */ public interface Create { } /** * 更新分组 */ public interface Update { } /** * 分组可以指定多个,用{}表示 * 分组为:默认分组、更新分组 */ @NotBlank(message = "姓名不能为空", groups = {Default.class, Update.class}) private String name; /** * 分组为添加分组 */ @Size(min = 3, max = 6, groups = {Create.class}) private List<String> friendNames; @Min(value = 18, message = "年龄未满18岁") @Max(value = 60, message = "年龄必须在60岁以下") private Integer age; private String tel; @DecimalMin(value = "30", message = "金钱不能小于30") private Integer money; }

把校验参数注解写在 Controller 上,别忘了在 Controller 上加 @Validated 注解哈!!!

@Validated @RestController public class ValidatorController { @Autowired private ValidatorService validatorService; @GetMapping public void validator() { ValidatorModel model = new ValidatorModel(); model.setName("张三"); model.setFriendNames(Arrays.asList("李四", "王五")); model.setAge(2); model.setTel("188888888881"); model.setMoney(100); model.setEmail("a"); validatorService.validator(model, "也可以在参数上做验证"); } @GetMapping("/group") public void validatorGroup(@Validated({ValidatorModel.Create.class}) ValidatorModel model) { validatorService.validatorGroup(model, "也可以在参数上做验证"); } }

这样就可以实现分组验证了。
注意:model 里有一个默认分组,如果指定分组就按分组来验证参数,而没有指定的分组属于默认分组,上图的 Controller 不会对默认分组进行验证,写成 @Validated({ValidatorModel.Create.class, Default.class})把默认分组加进去就可以验证了。如下:

@GetMapping("/group") public void validatorGroup(@Validated({ValidatorModel.Create.class, Default.class}) ValidatorModel model) { validatorService.validatorGroup(model, "也可以在参数上做验证"); }

自定义验证规则
那如果我想验证手机怎么办呢?它里面没有提供,不要慌小朋友,使用自定义注解验证就可以了,它提供了接口我们只需要实现一下就好了。

首先需要我们自定义一个验证手机号的注解(MonkeyTel),并指定其实现类,在实现写验证的逻辑就可以了。注解如下:

@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.FIELD}) // 指定真正实现校验规则的类 @Constraint(validatedBy = MonkeyJavaTelImpl.class) public @interface MonkeyJavaTel { String message() default "手机号必须是11位"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }

实现类如下:

/** * @Author: LailaiMonkey * @Description: * String:参数类型 * @Date:Created in 2020-04-17 15:19 * @Modified By: */ public class MonkeyJavaTelImpl implements ConstraintValidator<MonkeyJavaTel, String> { /** * 手机号是十一位为ture * @param value 值 * @param context * @return */ @Override public boolean isValid(String value, ConstraintValidatorContext context) { return value.length() == 11; } }

项目结构如下:
忽略 monkeyValidator 包,自定义注解校验规则,有兴趣的小伙伴可以看下一篇博客:自定义校验注解框架自定义校验注解框架

自定义验证规则
缺点:
此注解只能写有接口或 Controller 上才管用,如果写在实现类上是无效的。而且逻辑都写在实现类上,不知道哪些参数进行验证,还得返回到接口或 Controller 上查询才可以。
不支持 List 集合验证,实现起来困难,只支持简单 model 验证。
分组验证只能写在 Controller 上,写在接口不起作用(坑)。
如果一个接口有多个实现类这个注解就不能再用了。

优点:
自定义注解实现简单,上手快。

使用工具类校验
校验工具类:

package com.alibaba.banff.web.util; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.groups.Default; /** * 校验工具类 * * @author lizhilong */ public class ValidationUtils { private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); public static <T> ValidationResult validateEntity(T obj) { ValidationResult result = new ValidationResult(); Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class); // if( CollectionUtils.isNotEmpty(set) ){ if (set != null && set.size() != 0) { result.setHasErrors(true); Map<String, String> errorMsg = new HashMap<String, String>(); for (ConstraintViolation<T> cv : set) { errorMsg.put(cv.getPropertyPath().toString(), cv.getMessage()); } result.setErrorMsg(errorMsg); } return result; } public static <T> ValidationResult validateProperty(T obj, String propertyName) { ValidationResult result = new ValidationResult(); Set<ConstraintViolation<T>> set = validator.validateProperty(obj, propertyName, Default.class); if (set != null && set.size() != 0) { result.setHasErrors(true); Map<String, String> errorMsg = new HashMap<String, String>(); for (ConstraintViolation<T> cv : set) { errorMsg.put(propertyName, cv.getMessage()); } result.setErrorMsg(errorMsg); } return result; } }

校验工具类返回的数据 ValidationResult(省略 getset):

package com.aliyun.prophet.facade.partner.flaw; import java.util.Map; /** * 校验结果 * * @author lizhilong */ public class ValidationResult { // 校验结果是否有错 private boolean hasErrors; // 校验错误信息 private Map<String, String> errorMsg; }

Person 类(省略 getset):

package com.aliyun.prophet.facade.partner.flaw; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.Range; public class Person { @Length(max=20,message="姓名长度不能大于20") @NotEmpty(message="姓名不能为空") private String name; @Range(min = 0, max = 1, message = "性别只能输入只能输入0或1") private Integer gender; private Integer age; }

使用方法:

/** * * @author: lizhilong */ public class Test { @org.junit.Test public void testValidation(){ Person person = new Person(); person.setAge(12); person.setGender(2); // person.setName("李智龙"); ValidationResult result = ValidationUtils.validateEntity(person); Map<String, String> map = result.getErrorMsg(); boolean isError = result.isHasErrors(); System.out.println("isError: " +isError); System.out.println(map); } }

打印结果:

isError: true {gender=性别只能输入只能输入0或1, name=姓名不能为空}

是不是很简单呀,几步搞定,根本不用 spring 便可封装一个好用的工具类
————————————————
版权声明:本文为 CSDN 博主「熬夜是小狗」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/icannotdebug/article/details/78708202

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8216 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    947 引用 • 1460 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
zhaozhizheng
没有人会关心你付出过多少努力,撑得累不累,摔得痛不痛,他们只会看你最后站在什么位置,然后羡慕或者鄙夷 北京

推荐标签 标签

  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 642 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 287 关注
  • Access
    1 引用 • 3 回帖 • 3 关注
  • RemNote
    2 引用 • 16 回帖 • 20 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    947 引用 • 1460 回帖 • 1 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    178 引用 • 1267 回帖
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖 • 5 关注
  • 浅吟主题

    Jeffrey Chen 制作的思源笔记主题,项目仓库:https://github.com/TCOTC/Whisper

    1 引用 • 28 回帖
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖 • 2 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 37 关注
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 512 关注
  • Office

    Office 现已更名为 Microsoft 365. Microsoft 365 将高级 Office 应用(如 Word、Excel 和 PowerPoint)与 1 TB 的 OneDrive 云存储空间、高级安全性等结合在一起,可帮助你在任何设备上完成操作。

    5 引用 • 34 回帖
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    36 引用 • 200 回帖 • 31 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 518 关注
  • gRpc
    11 引用 • 9 回帖 • 99 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 3 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    80 引用 • 396 回帖
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    171 引用 • 1537 回帖 • 1 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 655 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    7 引用 • 69 回帖 • 5 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 639 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 1 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    954 引用 • 944 回帖 • 1 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 672 关注