Java Bean Validation 不适用Spring的情况下自定义validation注解

Java Bean Validation(也称为 JSR 380,为 Bean Validation 2.0 规范)提供了一套基本的注解,用于定义和验证 Java Bean 的属性。例如:

@NotNull:属性不能为空
@Size:字符串、集合或数组的大小有约束
@Min 和 @Max:数值的最小值和最大值
@Pattern:字符串必须匹配正则表达式
等等
这些注解是由 Bean Validation 规范定义的,可以通过例如 Hibernate Validator 的实现来使用。

0. Maven 依赖

        <dependency><groupId>jakarta.validation</groupId><artifactId>jakarta.validation-api</artifactId></dependency><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId></dependency>

1. 定义一个注解接口

@Constraint(validatedBy = RegexValidator.class)
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface RegexValidation {String message() default "Invalid value";String pattern();Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};

解析

类注解
@Constraint(validatedBy = RegexValidator.class)
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface RegexValidation {
@Constraint(validatedBy = RegexValidator.class):
标记这个注解作为一个验证注解。
validatedBy 属性指定了用于实际验证的类,这里是 RegexValidator.class。这意味着会有一个 RegexValidator 类来实现对这个注解的验证逻辑。
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE }):
这个元注解指定了 @RegexValidation 可以应用的程序元素类型。
ElementType.FIELD:表示这个注解能用于字段上。
ElementType.ANNOTATION_TYPE:表示这个注解可以用在其他注解上(元注解)。
@Retention(RetentionPolicy.RUNTIME):
这个元注解指定了 @RegexValidation 的保留策略。
RetentionPolicy.RUNTIME:表示注解将在运行时保留,可以通过反射进行读取。
定义注解的属性
String message() default "Invalid value";
message():
定义验证失败时的默认错误消息。
default "Invalid value":提供了一个默认值 "Invalid value"。
String pattern();
pattern():
定义一个字符串类型的属性,用于存储正则表达式模式。
没有默认值,所以这是一个必须属性,使用注解时必须提供。
Class<?>[] groups() default {};
groups():
用于分组验证,这使得注解可以在不同的验证组中使用。
默认是一个空数组。
Class<? extends Payload>[] payload() default {};
payload():
提供了负载信息的一种方式,可以用于传递元数据给约束。
默认是一个空数组。
整个注解定义总结
@RegexValidation 注解是一个自定义的验证注解,允许你对字段进行正则表达式匹配验证。该注解需要一个 pattern 属性来指定要匹配的正则表达式,并且通过 message 属性自定义验证失败时的错误信息。

2. 定义一个验证器

public class RegexValidator implements ConstraintValidator<RegexValidation, String> {private Pattern pattern;@Overridepublic void initialize(RegexValidation constraintAnnotation) {this.pattern = Pattern.compile(constraintAnnotation.pattern());}@Overridepublic boolean isValid(String string, ConstraintValidatorContext context) {if (string == null || string.isBlank()) {return true;}Matcher matcher = pattern.matcher(string);StringBuilder invalidChars = new StringBuilder();while (matcher.find()) {invalidChars.append(matcher.group());}if (invalidChars.length() > 0) {context.disableDefaultConstraintViolation();context.buildConstraintViolationWithTemplate(String.format("Invalid characters found: \"%s\"", invalidChars)).addConstraintViolation();return false;}return true;}
}

解析:

RegexValidator 类的作用是基于自定义注解 @RegexValidation 对字符串进行正则表达式匹配验证。其核心逻辑是初始化时编译正则表达式,然后验证时检查输入字符串是否完全匹配该正则模式,若存在不匹配字符则记录并返回验证失败。此过程实现了灵活且详细的输入验证,非常适合用于需要复杂输入约束的场景。

3. 定义一个组合注解类

@Constraint(validatedBy = {})
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@NotBlank(message = "Name must not be blank")
@Length(min = 3, max = 256, message = "Name length must be between 3 and 256 characters")
@SafeHtml
@RegexValidation(pattern = "[\\x{0001f300}-\\x{0001f64f}]|[\\x{0001f680}-\\x{0001f6ff}<>#%]")
public @interface LongName {String message() default "Invalid name";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};}

解析

这个注解结合了多个验证器来对目标字段进行综合验证。逐行解析这个注解的定义,有助于理解它是如何工作的,以及它在实际使用中可以提供哪些功能。注解定义部分
@Constraint(validatedBy = {})
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {}):这一行表明这是一个验证注解。
validatedBy 属性指定了需要用哪个验证器类来实现这个注解的验证逻辑。在这里,它是一个空数组 {},表示不指定特定的验证器类。实际上,验证的逻辑由注解内部包含的其他注解来实现。
@Target({ ElementType.FIELD }):该元注解描述了 @LongName 可以被应用到程序元素的类型上。
ElementType.FIELD 表示这个注解只能用在字段上。
@Retention(RetentionPolicy.RUNTIME):该元注解描述了 @LongName 的生命周期。
RetentionPolicy.RUNTIME 表示这个注解将在运行时保留,因此可以通过反射机制读取注解信息。
验证注解部分
@NotBlank(message = "Name must not be blank")
@Length(min = 3, max = 256, message = "Name length must be between 3 and 256 characters")
@SafeHtml
@RegexValidation(pattern = "[\\x{0001f300}-\\x{0001f64f}]|[\\x{0001f680}-\\x{0001f6ff}<>#%]")
@NotBlank(message = "Name must not be blank"):表示被注解的字段不能为空白字符串。
如果验证失败,会显示消息 "Name must not be blank"。
@Length(min = 3, max = 256, message = "Name length must be between 3 and 256 characters"):验证字符串长度需要在 3256 个字符之间。
如果长度不符合,会显示消息 "Name length must be between 3 and 256 characters"。
@SafeHtml:表示被注解的字段必须是安全的 HTML 内容。这个注解通常会用来防止跨站脚本(XSS)攻击。
@RegexValidation(pattern = "[\\x{0001f300}-\\x{0001f64f}]|[\\x{0001f680}-\\x{0001f6ff}<>#%]"):自定义一个正则表达式验证:只能包含特定的 Unicode 范围字符和某些标点符号。
应用的正则表达式模式为 "[\\x{0001f300}-\\x{0001f64f}]|[\\x{0001f680}-\\x{0001f6ff}<>#%]"。
组合注解定义的属性部分
public @interface LongName {String message() default "Invalid name";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};}
String message() default "Invalid name";:
提供默认的错误消息,尽管这个信息对组合注解本身没有太大意义,因为每个具体注解都有自己的错误消息。
Class<?>[] groups() default {};:
用于分组验证。
Class<? extends Payload>[] payload() default {};:
用于传递支付信息。
总结
@LongName 是一个组合注解,它结合了多个标准验证注解(例如 @NotBlank, @Length, @SafeHtml and @RegexValidation)的功能。这个组合注解对于需要进行多种综合验证的场景非常有用,使代码更加简洁和可读。同时,组合注解可以减少重复代码,提高开发效率。

4. 实体类字段中注解的使用

public class User {@LongNameprivate String name;// getters 和 setters
}

name 字段将会受到四个不同注解的联合验证:@NotBlank, @Length, @SafeHtml, 和 @RegexValidation。这简化了代码,将多重验证集中在一个地方声明。此外,组合注解提高了代码的可读性和维护性。

5. Spring 注解的优势

Spring 框架的优势
Spring 框架在Bean Validation的基础上进行了很多增强和扩展,为开发者提供了更多的便利和功能:

更强的依赖注入和配置管理:

Spring 框架提供了功能强大且易于使用的依赖注入容器,帮助你轻松管理对象的创建和依赖。
自动校验:

Spring MVC 和 Spring Data 可以自动与 Bean Validation 集成。例如,你可以在控制器方法中直接使用 @Valid 注解,使得请求参数在进入控制器方法之前就被验证。
@PostMapping(“/users”)
public ResponseEntity createUser(@Valid @RequestBody User user) {
// 如果 user 无效,Spring 会自动返回 400 错误代码
return ResponseEntity.ok(userService.save(user));
}
简化的配置:

Spring Boot 通过自动配置大大简化了 Bean Validation 的集成,可以快速上手,并且减少了繁琐的配置过程。
国际化 (i18n) 支持:

Spring 提供了强大的国际化支持,可以轻松地为不同的地区和语言配置验证消息。
高级功能和扩展:

通过自定义注解和验证器类,Spring 框架可以更灵活地满足复杂的业务需求。例如,可以将自定义验证逻辑注入到服务中来实现高级验证逻辑。
@Component
public class CustomValidator implements ConstraintValidator<CustomConstraint, String> {
@Override
public void initialize(CustomConstraint constraintAnnotation) {
}

@Override
public boolean isValid(String value, ConstraintValidatorContext context) {return "specialValue".equals(value);
}

}
与其他Spring模块的深度集成:

Spring 框架与 Spring Security、Spring Data、Spring Cloud 等其他模块紧密集成,这意味着你的验证逻辑可以更加一致和集中管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/67080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VScode 配置 C语言环境

遇到的问题集合 mingw官方下载网站&#xff08;https://sourceforge.net/projects/mingw-w64/files/&#xff09;更新之后&#xff0c;与网上大多数教程上写的界面不同了。 网上大多数教程让下载这个&#xff1a; 但是现在找不到这个文件。 写hello.c文件时&#xff0c;报错&…

语音技术与人工智能:智能语音交互的多场景应用探索

引言 近年来&#xff0c;智能语音技术取得了飞速发展&#xff0c;逐渐渗透到日常生活和各行各业中。从语音助手到智能家居控制&#xff0c;再到企业客服和教育辅导&#xff0c;语音交互正以前所未有的速度改变着人机沟通的方式。这一变革背后&#xff0c;人工智能技术无疑是关键…

前端依赖安装指南

前端依赖安装指南 一、NVM管理工具安装 1.在 Windows 上安装 下载 NVM for Windows 的安装程序&#xff1a;(最新版本可以在 nvm-windows Releases 页面 找到)运行下载的安装程序并按步骤操作。 2.配置 NVM exe安装自动配置环境变量 3. 验证 NVM 安装 验证 NVM 是否成功…

使用sqlplus的easy connect时如何指定是链接到shared server还是dedicated process

在oracle配置了shared server的情况下 可以使用 :shared来指定链接到shared server也可以默认不指定 不指定的情况下会默认链接到shared server 如果想链接到 dedicated process 则必须显式指定链接到dedicated process server type的类型包括DEDICATED, SHARED, or POOLED. […

26个开源Agent开发框架调研总结(2)

根据Markets & Markets的预测&#xff0c;到2030年&#xff0c;AI Agent的市场规模将从2024年的50亿美元激增至470亿美元&#xff0c;年均复合增长率为44.8%。 Gartner预计到2028年&#xff0c;至少15%的日常工作决策将由AI Agent自主完成&#xff0c;AI Agent在企业应用中…

IOS HTTPS代理抓包工具使用教程

打开抓包软件 在设备列表中选择要抓包的 设备&#xff0c;然后选择功能区域中的 HTTPS代理抓包。根据弹出的提示按照配置文件和设置手机代理。如果是本机则会自动配置&#xff0c;只需要按照提醒操作即可。 iOS 抓包准备 通过 USB 将 iOS 设备连接到电脑&#xff0c;设备需解…

Java面试核心知识4

公平锁与非公平锁 公平锁&#xff08;Fair&#xff09; 加锁前检查是否有排队等待的线程&#xff0c;优先排队等待的线程&#xff0c;先来先得 非公平锁&#xff08;Nonfair&#xff09; 加锁时不考虑排队等待问题&#xff0c;直接尝试获取锁&#xff0c;获取不到自动到队尾…

在 Linux 下Ubuntu创建同权限用户

我是因为不小心把最开始创建的用户的文件夹颜色搞没了&#xff0c;再后来全白用习惯了&#xff0c;就不想卸载了&#xff0c;像创建一个和最开始创建的用户有一样的权限可以执行sudo -i进入root一样的用户 如图这是最原始的样子 第一步 创建新用户&#xff0c;我这里是因为之前…

Microsoft Sql Server 2019 函数理解

说到函数&#xff0c;首先和存储过程作个比较吧&#xff0c;两者有一个共同点都是预编译优化后存储在磁盘中&#xff0c;所以效率 要比T-SQL高一点点。值得注意的是&#xff0c;存储过程可以创建或访问临时表&#xff0c;而函数不可以&#xff1b; 同时函数不可 以修改表中的数…

依据正则表达式拦截文本

正则表达式匹配 因为我是go语言&#xff0c;所以展示golang的 包&#xff1a;"github.com/dlclark/regexp2" 更多欢迎访问&#xff1a;www.zpf0000.com // CanMatchRegexp return bool 某个字符串是否匹配正则表达式 func CanMatchRegexp(message string, regexpSt…

学习及笔记

1、计算md5 md5sum 文件名 2、跨服务器复制 scp 文件 目标用户名目标Ip:目标路径 3、curl curl -X POST http://10.105.2.46/getUerls -H "Content-Type: application/json" -d {"id": 379, "userId": "lyc", "password":…

【Unity插件】解决移动端UI安全区问题 - Safe Area Helper

在移动端设计界面时&#xff0c;必须要考虑的就是UI的安全区。 Unity本身也提供了Safearea的API。 但在asset store时已经有人提供了免费的插件&#xff08;Safe Area Helper&#xff09;&#xff0c;我们可以直接使用。 插件链接&#xff1a; https://assetstore.unity.com/p…

机器学习之随机森林算法实现和特征重要性排名可视化

随机森林算法实现和特征重要性排名可视化 目录 随机森林算法实现和特征重要性排名可视化1 随机森林算法1.1 概念1.2 主要特点1.3 优缺点1.4 步骤1.5 函数及参数1.5.1 函数导入1.5.2 参数 1.6 特征重要性排名 2 实际代码测试 1 随机森林算法 1.1 概念 是一种基于树模型的集成学…

OpenAI 故障复盘 - 阿里云容器服务与可观测产品如何保障大规模 K8s 集群稳定性

本文作者&#xff1a; 容器服务团队&#xff1a;刘佳旭、冯诗淳 可观测团队&#xff1a;竺夏栋、麻嘉豪、隋吉智 一、前言 Kubernetes(K8s)架构已经是当今 IT 架构的主流与事实标准&#xff08;CNCF Survey[1]&#xff09;。随着承接的业务规模越来越大&#xff0c;用户也在使…

面试:C++类成员初始化顺序

1、非静态数据成员&#xff1a;按它们在类定义的声明顺序初始化&#xff0c;不会按它们在初始化列表的顺序。 2、静态数据成员&#xff1a;在main函数启动之前&#xff0c;并且只初始化一次 3、基类构造函数&#xff1a;如果类从一个或多个基类继承而来&#xff0c;基类的构造…

Vue.js 使用插槽(Slots)优化组件结构

Vue.js 使用插槽&#xff08;Slots&#xff09;优化组件结构 今天我们聊聊 Vue.js 的一个超实用功能——插槽&#xff08;Slots&#xff09;。插槽是 Vue 组件开发中的神器&#xff0c;用好它&#xff0c;你可以让组件变得更灵活、更可复用&#xff0c;还能写出优雅的代码结构…

SpringBoot 使用 Cache 集成 Redis做缓存保姆教程

1. 项目背景 Spring Cache是Spring框架提供的一个缓存抽象层&#xff0c;它简化了缓存的使用和管理。Spring Cache默认使用服务器内存&#xff0c;并无法控制缓存时长&#xff0c;查找缓存中的数据比较麻烦。 因此Spring Cache支持将缓存数据集成到各种缓存中间件中。本文已常…

机器学习全流程解析:数据导入到服务上线全阶段介绍

目录 1. 数据导入 2. 数据预处理 3. 超参数搜索与优化 4. 模型训练 5. 模型评估 6. 模型压缩与优化 7. 模型注册与版本管理 8. 服务上线与部署 总结 1. 数据导入 数据源&#xff1a;数据库、文件系统、API等。数据格式&#xff1a;CSV、JSON、SQL 数据库表、Parquet …

MySQL —— 在CentOS9下安装MySQL

MySQL —— 在CentOS9下安装MySQL 1.查看自己操作系统的版本2.找到对应的安装源3.上传我们在windows下&#xff0c;下载的文件&#xff0c;解压4.执行rpm命令&#xff0c;启用MySQL8仓库5.执行dnf install -y mysql-community-server6.设置开机自启动7.获得初始密码8.登录MySQL…

Center Loss 和 ArcFace Loss 笔记

一、Center Loss 1. 定义 Center Loss 旨在最小化类内特征的离散程度&#xff0c;通过约束样本特征与其类别中心之间的距离&#xff0c;提高类内特征的聚合性。 2. 公式 对于样本 xi​ 和其类别yi​&#xff0c;Center Loss 的公式为&#xff1a; xi​: 当前样本的特征向量&…