Spring Boot自定义验证消息与参数化

spring boot自定义验证消息与参数化

本教程将详细介绍如何在Spring Boot应用中,为自定义验证消息添加参数化功能。通过定义`ValidationMessages.properties`文件中的占位符,并结合自定义验证注解,我们可以实现类似`@Size`注解那样,在运行时动态替换消息中的参数,从而提供更加灵活和用户友好的错误提示信息。

Spring Boot验证消息机制概述

Spring Boot通过Hibernate Validator实现了JSR 380(Bean Validation 2.0)规范。默认情况下,当使用如@Size(max = 100)等内置验证注解时,其对应的错误消息可以从ValidationMessages.properties文件中获取。例如,定义javax.validation.constraints.Size.message=请输入一个值。最大长度为 {max}。,运行时{max}占位符会自动被注解中指定的max值替换。

这种参数化机制极大地提高了错误消息的灵活性。本教程的目标是,为我们自定义的验证规则实现类似的参数化功能,例如定义一个my.custom.message=嘿,我的自定义值是 {customValue},并让{customValue}在运行时被动态替换。

实现自定义参数化验证消息

要实现自定义参数化验证消息,我们需要完成以下几个步骤:

1. 定义自定义验证消息

首先,在项目的src/main/resources目录下创建(或修改)ValidationMessages.properties文件,并添加你的自定义消息及其参数占位符。

# 默认的Size验证消息示例javax.validation.constraints.Size.message=请输入一个值。最大长度为 {max}。# 自定义的参数化消息my.custom.message=嘿,我的自定义值是 {customValue}

这里,{customValue}就是我们希望在运行时动态替换的参数。

2. 创建自定义验证注解

接下来,我们需要创建一个自定义的验证注解。这个注解将作为我们自定义验证规则的入口,并负责提供参数值。

import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 自定义验证注解示例 */@Documented@Constraint(validatedBy = MyCustomValidator.class) // 指定实际的验证逻辑类@Target({ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER}) // 可以在字段、类、方法参数上使用@Retention(RetentionPolicy.RUNTIME)public @interface MyCustomAnnotation {    // 定义一个方法,其名称将作为消息中的占位符名称    String customValue() default "默认自定义值"; // 这个值将在消息中替换 {customValue}    // 验证失败时的消息key,指向 ValidationMessages.properties 中的定义    String message() default "{my.custom.message}";    Class[] groups() default {};    Class[] payload() default {};    // 如果需要在类级别进行验证,可能需要添加其他属性    @Target({ElementType.TYPE})    @Retention(RetentionPolicy.RUNTIME)    @Documented    @interface List {        MyCustomAnnotation[] value();    }}

关键点说明:

@Constraint(validatedBy = MyCustomValidator.class):指定了执行实际验证逻辑的类。我们将在下一步中创建它。String customValue() default “默认自定义值”;:这个方法定义了一个名为customValue的属性。它的名称(customValue)与ValidationMessages.properties中定义的占位符{customValue}相对应。当验证框架解析消息时,会查找注解中同名的方法来获取其值。String message() default “{my.custom.message}”;:指定了当验证失败时使用的消息键。它指向我们在ValidationMessages.properties中定义的自定义消息。

3. 实现自定义验证器

自定义验证器MyCustomValidator是执行实际验证逻辑的地方。它需要实现ConstraintValidator接口。

import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;/** * 自定义验证器示例 */public class MyCustomValidator implements ConstraintValidator {    private String requiredCustomValue;    @Override    public void initialize(MyCustomAnnotation constraintAnnotation) {        // 在验证器初始化时,可以获取注解中定义的属性值        this.requiredCustomValue = constraintAnnotation.customValue();        // 可以在这里进行一些预处理或配置    }    @Override    public boolean isValid(Object value, ConstraintValidatorContext context) {        // 实际的验证逻辑        // 假设我们验证传入的值是否与注解中定义的 customValue 相匹配        if (value == null) {            return false; // 或者根据业务逻辑返回 true/false        }        // 示例:如果传入的值是字符串,并且与requiredCustomValue相同,则通过        if (value instanceof String) {            return value.equals(requiredCustomValue);        }        // 对于其他类型,这里只是一个示例,实际应根据业务需求编写        return false;    }}

在initialize方法中,我们可以访问MyCustomAnnotation注解的实例,从而获取customValue()等属性的值。isValid方法则包含具体的验证逻辑。

4. 在模型中使用自定义注解

现在,我们可以在Spring Boot的数据模型(DTO或实体)中使用@MyCustomAnnotation了。

import javax.validation.constraints.NotBlank;import javax.validation.constraints.Size;public class MyDataForm {    @NotBlank(message = "名称不能为空")    @Size(max = 50, message = "名称长度不能超过 {max} 个字符")    private String name;    // 使用自定义注解,并传入 customValue 参数    @MyCustomAnnotation(customValue = "特定值A")    private String customField;    // 可以有其他字段...    // Getters and Setters    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getCustomField() {        return customField;    }    public void setCustomField(String customField) {        this.customField = customField;    }}

当customField的验证失败时(即MyCustomValidator的isValid方法返回false),验证框架会查找MyCustomAnnotation的message()方法,得到”{my.custom.message}”。然后,它会在ValidationMessages.properties中找到my.custom.message=嘿,我的自定义值是 {customValue}。接着,它会通过反射调用MyCustomAnnotation的customValue()方法,获取到我们设置的”特定值A”,并将其替换到消息中的{customValue}占位符。最终用户将看到类似“嘿,我的自定义值是 特定值A”的错误消息。

运行时参数替换原理

Spring Boot(通过Hibernate Validator)的验证框架在处理消息时,会执行一个插值(interpolation)过程。当一个消息字符串包含{placeholder}形式的占位符时,框架会尝试从以下几个源查找对应的值:

约束注解本身: 框架会查找当前触发验证的约束注解(例如@MyCustomAnnotation)中是否存在与占位符名称(例如customValue)同名的方法。如果找到,就调用该方法获取其返回值作为占位符的值。默认消息源: 如果未在注解中找到,它还会检查一些预定义的上下文(如ConstraintValidatorContext)或配置的MessageSource。

因此,只要你在自定义注解中定义了一个与消息占位符同名的方法(如customValue()),并在message()方法中引用了包含该占位符的键(如”{my.custom.message}”),框架就会自动完成参数的替换。

即使是像private static final String CUSTOM_STRING = “{my.custom.message}”;这样的字符串,只要它最终被用作某个验证约束的message属性值(例如,在自定义注解的message()方法中返回),其内部的占位符也会被验证框架正确解析和替换。

注意事项

ValidationMessages.properties文件位置: 确保该文件位于类路径下,通常是src/main/resources。如果需要支持国际化,可以创建ValidationMessages_zh_CN.properties等文件。参数名与注解方法名一致性: 消息中的占位符名称(如{customValue})必须与自定义注解中定义的方法名(如customValue())完全一致,包括大小写。默认值: 在自定义注解中为参数方法提供默认值(如customValue() default “默认自定义值”;)是一个好习惯,这使得注解在使用时可以省略该参数。错误消息的国际化: 通过创建不同语言环境的ValidationMessages_{locale}.properties文件,可以轻松实现验证消息的国际化。Spring Boot会自动根据请求的Accept-Language头或配置的LocaleResolver选择正确的语言文件。

总结

通过以上步骤,我们成功地为Spring Boot中的自定义验证消息实现了参数化功能。这种方法不仅使得错误提示更加动态和精确,也提升了用户体验。核心在于理解验证框架如何通过注解方法名与消息占位符的匹配来完成运行时值的注入。掌握这一技巧,可以为你的Spring Boot应用构建更加健壮和用户友好的数据验证机制。

以上就是Spring Boot自定义验证消息与参数化的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/198488.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
如何在mysql中使用事务保证数据完整性
上一篇 2026年9月10日 20:47:57
新公布三款锐意独游作品!NEOWIZ宣布参加“WePlay2025”
下一篇 2026年9月10日 20:51:59

相关推荐

  • Polarr的AI工具怎么裁剪图片?教你轻松实现高效图像裁剪

    Polarr的AI工具怎么裁剪图片?教你轻松实现高效图像裁剪Polarr的AI工具怎么裁剪图片?教你轻松实现高效图像裁剪Polarr的AI工具怎么裁剪图片?教你轻松实现高效图像裁剪Polarr的AI工具怎么裁剪图片?教你轻松实现高效图像裁剪

    Polarr的AI裁剪通过内容感知智能识别主体与构图焦点,提供如主体居中、构图优化和比例推荐等方案,操作上先导入图片,选择裁剪工具后AI即分析画面并生成多个推荐预设,用户可直接应用或手动微调,相比传统裁剪显著提升效率、辅助构图决策,尤其适用于社交媒体多平台比例适配,帮助保持视觉一致性并避免关键信息被…

    2026年9月24日 用户投稿
    500
  • 解决AWS S3 PHP SDK中SSL连接失败问题:证书验证与文件句柄限制

    本文旨在帮助开发者解决在使用AWS S3 PHP SDK时遇到的SSL连接失败问题,错误信息包括“fopen(): SSL operation failed with code 5”和“certificate verify failed”。文章将深入分析错误原因,并提供修改php.ini配置,指定证…

    2026年9月24日
    100
  • 在Hibernate中实现非关联实体间的ID引用与高效查询

    本教程探讨了在Hibernate应用中,如何在没有直接实体映射关系(如@OneToMany)的情况下,将一个实体(如父实体)生成的ID引用到另一个非关联实体(如日志实体)中。通过利用HQL/JPQL的JOIN…ON语法,即使没有显式ORM关系,也能实现基于共享ID字段的高效数据关联和查询…

    2026年9月24日
    500
  • mysql如何优化表结构?表结构设计方法

    设计和优化 mysql 表结构应从字段类型选择、主键与索引设计、冗余与范式处理、分表分区策略四个方面入手。1. 合理选择字段类型,如整数用 int/bigint,枚举值用 enum 或 tinyint,日期用 datetime,避免过度使用 text/blob;2. 主键建议使用自增整型,避免长字段…

    2026年9月24日
    1000
  • 有选择性地移除 WooCommerce 订单邮件中的产品购买备注

    本文将指导您如何针对特定的 WooCommerce 订单邮件通知,有选择性地移除产品购买备注,避免在所有邮件中都隐藏该信息。 使用 WooCommerce 钩子和全局变量进行控制 WooCommerce 允许开发者通过钩子(hooks)修改其核心功能。为了实现我们的目标,我们需要使用 woocomm…

    2026年9月24日
    200
  • 光追和DLSS/FSR技术,对游戏体验改变到底有多大?

    光追与DLSS/FSR结合带来颠覆性体验:光追实现真实光影,提升视觉真实感;DLSS/FSR通过AI超分技术保障高画质下的高帧率,二者协同达成电影级沉浸效果。 开启光追和DLSS/FSR后,游戏体验的变化是颠覆性的。它不只是画面更亮或帧数更高那么简单,而是从视觉真实感和操作流畅度两个维度,彻底改变了…

    2026年9月24日
    700
  • 升级Windows 10/11出现0xC1900101错误怎么办?

    错误代码0xC1900101通常由驱动冲突、磁盘空间不足或系统文件损坏引起。1、通过设备管理器更新过时驱动;2、确保C盘有20GB以上空间并清除SoftwareDistribution文件夹;3、使用SFC和DISM命令修复系统文件;4、重置Windows Update相关服务为自动启动并重启服务。…

    2026年9月24日
    100
  • 如何用HornilStylePix的AI裁剪图片?快速完成精准裁剪步骤

    HornilStylePix的AI裁剪功能可智能识别主体并推荐裁剪方案,支持手动调整与多种比例选择,提升裁剪效率和准确性,同时软件还具备调色、滤镜、批量处理等实用编辑功能。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ HornilStyl…

    2026年9月24日
    800
  • VSCode如何设置智能代码重构建议 VSCode自动化重构工具的配置优化

    vscode的智能代码重构建议不出现时,首先检查文件类型是否受支持、对应语言扩展是否安装启用、项目根目录是否有jsconfig.json或tsconfig.json等配置文件;2. 确保editor.lightbulb.enabled为true以显示灯泡提示;3. 通过设置editor.codeac…

    2026年9月24日
    700
  • phpMyAdmin快速导出文件字符集配置指南

    本文详细介绍了phpMyAdmin快速导出功能中文件字符集的默认设置及其配置方法。默认情况下,快速导出生成的文件采用UTF-8编码。用户可以通过修改phpMyAdmin的配置文件config.inc.php,利用$cfg[‘Export’][‘charset&#8…

    2026年9月24日
    100
  • JavaScript 中替换 JSON 数据值的实用指南

    本文旨在提供一个清晰、简洁的 JavaScript 教程,讲解如何根据特定条件,利用响应数据中的值替换 JSON 数据中的指定字段。我们将通过实例代码演示如何处理包含 “All” 值的 Emp_Id 字段,并使用响应数据中的 ID 值进行替换,最终生成期望的 JSON 数据结…

    2026年9月24日
    200
  • 基于属性配置动态创建 Spring Boot Bean

    本文介绍了如何在 Spring Boot 应用中基于配置属性的值动态创建 Bean。通过使用 @ConditionalOnProperty 注解,可以根据指定的属性是否存在以及其值来决定是否创建某个 Bean,从而实现灵活的配置和 Bean 的动态加载。本文将提供详细的代码示例和使用说明,帮助开发者…

    2026年9月24日
    100
  • PCIe 4.0和PCIe 5.0的固态硬盘,实际使用差别大吗?

    PCIe 5.0 SSD相比4.0在游戏加载中提升有限,仅快1-2秒且感知不强;但在视频剪辑、AI训练等生产力场景下,顺序读写速度提升近一倍,渲染和文件传输效率显著提高。 PCIe 4.0和5.0固态硬盘在实际使用中的差别,主要看你怎么用。对大多数普通用户来说,差距没想象中大;但如果你干的是专业活儿…

    2026年9月24日
    200
  • Claude的AI混合工具如何使用?提升文本生成效率的完整方法

    Claude的AI混合工具通过组合多种AI模型优化文本生成,首先明确需求,如创意写作或代码生成,再选择适配模型如GPT-3、Codex等,设计多模型协作流程,结合LangChain等工具调用API,通过Prompt工程明确指令、风格与范围,并不断迭代优化,解决模型兼容性、数据格式与成本控制等技术挑战…

    2026年9月24日
    100
  • Laravel Blade中条件隐藏元素的优雅实践

    本文探讨了在Laravel Blade模板中如何高效地实现HTML元素的条件隐藏。针对传统@if-@else语句导致代码冗余的问题,教程提出使用Blade的内联三元运算符在style属性中动态控制display: none,从而避免重复代码,提升模板的可读性和维护性。此外,还将介绍如何利用CSS类和…

    2026年9月24日
    100
  • 将 double 类型窄化为 float 类型时出现不兼容的返回类型

    本文旨在解决在 Java 中将父类的 double 类型返回值在子类中覆盖为 float 类型时遇到的类型不兼容问题。我们将深入探讨问题的原因,并提供使用泛型来解决此问题的有效方法,帮助开发者避免类似错误,并编写更健壮和灵活的代码。 问题分析:返回类型不兼容的原因 在面向对象编程中,子类可以覆盖(O…

    2026年9月24日
    500
  • 三大运营商 eSIM 手机业务全面落地 办理渠道各有侧重

    10 月 14 日消息,日前,中国联通与中国移动正式获准开展 esim 手机运营服务的商用试验,中国电信也同步取得工信部颁发的 esim 手机商用试验许可,这意味着国内三大运营商在 esim 手机业务方面已全面进入实际应用阶段。 中国移动用户可选择前往线下营业厅办理 eSIM 相关业务,也可通过中国…

    2026年9月23日
    200
  • 如何在Linux中处理只读文件系统?

    文件系统变只读主因是硬件故障或文件系统错误触发保护机制,需先用mount命令检查挂载状态,若显示ro则尝试remount,rw;2. 若失败应排查dmesg日志中的I/O错误,并在未挂载时用fsck修复文件系统;3. 使用smartctl检测磁盘健康,若硬盘已损坏需及时更换;4. 检查/etc/fs…

    2026年9月23日
    600
  • 如何在mysql中使用数值函数计算

    答案:MySQL数值函数用于执行数学运算,如ABS、ROUND、FLOOR、CEIL、MOD、POWER、SQRT等,可对数据直接计算。例如用ROUND四舍五入价格,TRUNCATE截断小数,FLOOR取整,MOD求余判断奇偶,SQRT开方,还可结合AVG、MAX等聚合函数使用,提升查询效率并减少应…

    2026年9月23日
    100
  • laravel API资源类怎么格式化JSON输出_laravel API资源类JSON格式化教程

    使用 Laravel API 资源类可统一 JSON 返回格式,通过 make:resource 创建资源类,在 toArray 中定义字段,控制器中返回 new UserResource($user) 或 UserResource::collection() 实现数据结构化输出。 如果您在使用 L…

    2026年9月23日
    400

发表回复

登录后才能评论
关注微信