IDEA国际化资源Key无法全局重命名的解决方案

2023-11-18

一、前言

最近在开发中使用到了HibernateValidator进行入参校验以及错误消息的国际化支持。大家应该都知道在使用HibernateValidator进行校验的时候,我们只需在需要在校验的变量上添加相应的注解,同时在message中指定对应的错误信息的国际化资源Key即可(如下图)。这里的message对应的国际化资源key必须要使用大括号

上述使用方法是HibernateValidator的标准使用方法,功能实现上并没有什么毛病。但是这种方法却带来了一个弊端,它可能增加咱们得开发工作量,甚至会影响业务。为什么会这个问题呢?接下来咱们一起看看下面这个问题。

如果咱们需要对消息key进行全局重命名,比如将图中的validation.dataSourceVO.name.notBlank修改为validation.dataSourceVO.name.notEmpty,大家想想咱们一般会怎么操作。

很明显我们都会使用IDEA的重命名功能,直接对这个变量进行重命名。修改完成后,注解中的key和message.properties文件中对应的key、以及所有代码中对应的该变量都会同步修改。对么?!

对,也不对!首先这种思路完全没问题,因为使用IDEA的重命名能够将所有关联的地方的内容全部都进行修改。但是这种方式在这里却不行!为什么呢?因为我们使用了大括号对消息key进行包围。使用了大括号后,IDEA根本不会提供重命名功能。

如下图,当有大括号后在refactor中没有rename功能。但当没有大括号后refactor中则出现嘞rename功能。

  

上面这种现象就导致了当我们要重命名消息key的时候,我们不得不一处一处将所有涉及的地方手动修改。这就带来如下两个问题:

a、增加了工作量。

b、可能因为自己没有修改全面导致业务出错。

为了避免上述问题,咱们就需要在注解中直接使用没有大括号的消息Key。所以我们需要让HibernateValidator支持没有大括号的消息Key。这具体怎么实现呢?经过不断地折腾深入源码,我终于找到了解决办法。下面给大家分享下解决思路和办法。

1、HibernateValidator的流程

 

首先我们简单整理下HibernateValidator校验失败后提示错误消息的整个流程。如上图:

a、用户提交请求,然后HibernateValidator基于注解内容进行校验。

b、如果未通过校验,则获取注解中的错误消息Key,如:{validation.name.empty}

c、然后进行一些处理,最后去掉错误消息Key的大括号得到真正的错误消息Key,如:validation.name.empty

d、最后根据真实的消息Key(validation.name.empty)去messages.properteis文件中查找对应的错误消息,并返回给调用方。

2、方案1:让Hibernate不判断大括号

基于上述流程,我们可以看到HibernateValidator认为使用了大括号的资源Key才是国际化资源Key。所以咱们可以想到的最简单的办法就是去掉图中2的逻辑,即让HibernateValidator不对大括号进行处理(即没有大括号的资源Key也是国际化资源Key)。于是通过深入源码进行追踪,砸门能够发现大括号的处理在如下的一个私有方法(AbstractMessageInterpolator.removeCurlyBraces)中进行。如下图,其处理还有点暴力,直接去掉消息Key第一个和最后一个字符(前面有地方判断是否有大括号)。

 所以如果想从这个地方入手就必须重写其调用位置的逻辑,由于其调用逻辑非常复杂(有兴趣大家可以自己跟踪下代码),所以需要重写很多HibernateValidator的原始逻辑。最终肯定能够实现功能,但是这种方式却不可取。因为咱们在修改源码实现业务的时候有一个基本的原则:尽量减少对原始代码的重写和修改。因为过多的修改会带来很多问题,比如:

a、后续底层框架升级后咱们修改的大量代码逻辑很可能得不到及时升级。从而导致底层BUG得不到及时解决,新功能得不到及时升级。

b、由于修改了大量的底层代码,因此维护成本也会增加。

所以,这种方法咱们暂时放弃,接下来我们另谋出路。

3、方案2:给资源自动添加大括号

让HibernateValidator不判断大括号的方案不可行后,咱们则可以换一种思路。即让注解中配置的时候使用不含大括号的消息Key,但在HibernateValidator处理之前(图中标记1的位置)给他加上去。

于是咱们进一步分析底层源码逻辑,发现所有消息Key从注解中解析出来后,就会调用AbstractMessageInterpolator.interpolate方法进行后续的解析操作(处理消息Key、去除大括号、从messages.properties中获取错误消息等)。该方法本身是一个public方法,子类可以继承和处理。

基于该思路,咱们重写实现了HibernateValidator使用的ResourceBundleMessageInterpolator(AbstractMessageInterpolator的实现类),并修改了interpolate的处理逻辑。即在调用真实的处理逻辑前面,咱们根据条件给消息Key添加上大括号。

 已经准备好会后,最后就是将自定义的RasMsgResourceBundleMessageInterpolator设置到HibernateValidator中,如下图在构建HibernateValidator的时候设置即可。

 4、方案总结

通过分析可知,两种方案很明显方案2要高级很多。它在解决问题的同时还符合咱们的源码修改基本原则:对源码进行最小的改动!其实通过代码可知,咱们方案2根本就没有对源码进行修改。只是利用继承的原理通过子类重写interpolate方法实现来实现了咱们需要的功能。 

三、惯例

如果你喜欢本文或觉得本文对你有所帮助,欢迎一键三连支持,非常感谢。

如果你对本文有任何疑问或者高见,欢迎添加公众号lifeofcoder共同交流探讨(添加公众号可以获得楼主最新博文推送以及”Java高级架构“上10G视频和图文资料哦)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

IDEA国际化资源Key无法全局重命名的解决方案 的相关文章

  • 使用选项卡式活动中的捆绑包将值从活动传递到片段

    我是一个java文盲 但仍在尝试开发一个供我个人使用的应用程序 我从 android studio 的 Tabbed Activity 开始 除了 MainActivity 中的一个片段和一个包之外 大部分没有改变 这是我的代码 主要活动
  • V8 如何管理它的堆?

    我知道V8的垃圾收集在工作时 会从GC的root开始追踪 这样无法到达的对象就会被标记然后被清除 我的问题是GC是如何遍历那些对象的 必须有一个数据结构来存储所有可达或不可达的对象 位图 链接表 顺便说一句 JVM 也做同样的事情吗 艾伦秀
  • Spring webflow 应用程序:HTTP 302 暂时移动

    我的 java 应用程序中的每个请求都会生成另外 2 个带有 HTTP 302 错误的请求 例如 如果请求查看名为板 html 这个请求是从首页 html 我收到按以下顺序生成的 3 个请求 POST home html 302 Moved
  • JUnit 使用 Mockito 测试异步方法

    我已经使用 Spring Framework 版本 5 0 5 RELEASE 在 Java 1 8 类中实现了异步方法 public class ClassToBeTested Autowired private MyComponent
  • java“void”和“非void”构造函数

    我用 java 编写了这个简单的类 只是为了测试它的一些功能 public class class1 public static Integer value 0 public class1 da public int da class1 v
  • 删除 servlet 中的 cookie 时出现问题

    我尝试使用以下代码删除 servlet 中的 cookie Cookie minIdCookie null for Cookie c req getCookies if c getName equals iPlanetDirectoryPr
  • 如何在 OpenAPI 3.0 中定义字节数组

    我正在将 API 从 Swagger 2 0 迁移到 OpenAPI 3 0 在 DTO 中 我有一个指定为字节数组的字段 Swagger 对 DTO 的定义 Job type object properties body type str
  • 如何模拟一个方面

    我目前正在使用aspectj 开发一些监控工具 因为这个工具应该是技术独立的 尽可能 所以我没有使用 Spring 进行注入 但我希望我的方面能够经过单元测试 方面示例 Aspect public class ClassLoadAspect
  • Java 的 QP 求解器 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • JSP 标签+ scriptlet。如何启用脚本?

    我有一个使用标签模板的页面 我的 web xml 非常基本 我只是想在页面中运行一些代码 不 我对标签或其他替代品不感兴趣 我想使用不好的做法 scriptlet 哈哈 到目前为止 我收到了 HTTP ERROR 500 错误 Script
  • 您能让 Tomcat 6 stdout.log 文件表现得像 log4j DailyRollingFileAppender 吗?

    我们使用的是 Tomcat 6 的 Windows 安装 默认情况下 我们应用程序的 log4j 输出将转到 catalina base logs stdout log 文件 该日志文件仅在我们重新启动 Tomcat 时滚动 并且文件名始终
  • java JFileChooser 文件大小过滤器

    我知道我可以按文件类型进行过滤 但是可以按文件大小进行过滤吗 例如 JFileChooser 仅显示 3 MB 以内的图片 简短的回答应该是 你尝试过什么 长答案是肯定的 JFileChooser fc new JFileChooser f
  • 如何使用 Java 原生接口从 Java 调用 Go 函数?

    可以通过以下方式调用 C 方法JNA https en wikipedia org wiki Java Native AccessJava 中的接口 如何使用 Go 实现相同的功能 package main import fmt impor
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • Java G1 GC 处理引用对象运行缓慢

    我已经在 J ava 上运行了计数器 它24小时工作 每秒点击通过100次左右 白天 GC 处理时间从 20 60 毫秒缓慢上升到 10000 60000 毫秒 然后下降到 20 60 毫秒 这种模式不时地重复 从 GC 日志中我发现 GC
  • 源服务器未找到目标资源的当前表示或不愿意透露该表示存在

    web xml
  • java 属性文件作为枚举

    是否可以将属性文件转换为枚举 我有一个包含很多设置的属性文件 例如 equipment height equipment widht equipment depth and many more like this and not all a
  • 是什么原因导致“对象不是声明类的实例”? [复制]

    这个问题在这里已经有答案了 可能的重复 使用反射调用方法时 为什么会出现 对象不是声明类的实例 https stackoverflow com questions 7202988 why do i get object is not an
  • Scala repl 抛出错误

    当我打字时scala在终端上启动 repl 它会抛出此错误 scala gt init error error while loading AnnotatedElement class file usr lib jvm java 8 ora
  • Java泛型类型

    当我有一个界面时 public interface Foo

随机推荐

  • rocksd mysql_mysql rocksdb使用报告

    作者 某网盘DBA 转发已经过作者同意 如果有其他问题请及时联系 非经过允许请勿随意转发 尊重版权 感谢 背景 rocksdb是facebook基于google的leveldb二次开发的key value存储引擎 目前 facebook已将
  • cenos 6.4 安装memcached 服务端

    本文查考借鉴 yum 安装memcached 前提 阿里云 EDS 服务器 操作系统 CentOs 6 4 第一步 查询memcached 安装资源包信息 yun search memcached 该指令可以查询yum库中 所包含memca
  • Centos 安装Vsftpd

    1 安装VSFTP 1 root localhost yum y install vsftpd 2 配置vsftpd conf文件 root localhost vi etc vsftpd vsftpd conf 001 002 003 0
  • tkinter绘制组件(12)——表格

    tkinter绘制组件 12 表格 引言 构思 外观 绘制方法 布局 函数结构 绘制表头 绘制表格内容 获取高度和重绘 完整代码函数 效果 测试代码 最终效果 2021 12 12新样式 2022 1 2新样式 2022 7 3新功能 补充
  • 知识图谱实现步骤和用到的方法

    PDF 下载 https download csdn net download nrlovestudy 10938925 参考资料 1 知识图谱入门 一 知识图谱与语义技术概览 https blog csdn net pelhans art
  • 【CSS】background相关属性深入学习

    最近一次需求中对于background相关的一些属性使用较多 总结下 希望提高下次的开发效率 background属性 background color background image background position backgr
  • .NET面试题——第7篇 C#类和对象

    1 什么是类和对象以及关系 对象 一种具有状态 属性 和行为 方法 的编程实体 用于描述现实世界的某个具体事物 类 具用一系列对象共同特征和行为的通用类型 对象和类的关系 类是对象的抽象 而对象是类的具体实例 类是抽象的 不占用内存 而对象
  • go爬虫框架colly的精简讲解

    1 拉取软件包 go get github com gocolly colly 2 创建colly的收集器 colly NewCollector 可以在创建的时候进行配置 c colly NewCollector colly AllowUR
  • Java 断点调试 循环调试

    java断点调试 以eclipse为例 1 基础调试 这里都是一些基础 除了最后一个都十分常用 名称 快捷键 作用 Resume F8 运行至下一断点 Step Into F5 进入方法 Step Over F6 运行完当前语句 User
  • PCL 点云按高程渲染颜色

    目录 一 算法原理 二 代码实现 三 结果展示 四 CloudCompare 五 备注 一 算法原理 首先按照Z轴方向求取所在点云的高程极值 包括高程最大值与最小值 计算高程中值 然后选取渲染的红 绿 蓝三种颜色的值 最后 自上而下 为红绿
  • NBA的字母哥如何拿到2415万美金年薪

    前言 NBA是世界上最成功的体育联盟之一 为了制定合理的运作规范 联盟会与球员工会签署劳资协议 协议里规定了球队的工资帽 一支球队球员工资总额的上限 顶薪 球员薪水的上限 底薪 球员的最低薪水 和其他规范 2011年 经历了停摆事件 联盟和
  • 一张图理清ASP.NET Core启动流程

    1 引言 对于ASP NET Core应用程序来说 我们要记住非常重要的一点是 其本质上是一个独立的控制台应用 它并不是必需在IIS内部托管且并不需要IIS来启动运行 而这正是ASP NET Core跨平台的基石 ASP NET Core应
  • JS 数组定义及详解

    一 数组简介 1 什么是数组 数组是值的有序集合 每个值叫做元素 每个元素在数组中都有数字位置编号 也就是索引 JS中的数组是弱类型的 数组中可以含有不同类型的元素 数组元素甚至可以是对象或其他数组 例如 var arr 1 true nu
  • kubernetes运维---calico之ipip模式抓包分析

    一 calico介绍 Calico是Kubernetes生态系统中另一种流行的网络选择 虽然Flannel被公认为是最简单的选择 但Calico以其性能 灵活性而闻名 Calico的功能更为全面 不仅提供主机和pod之间的网络连接 还涉及网
  • 功能实现:Unity中一个动画,只播放中间指定的一截,而且循环播放

    一 要播放的动画 直播中间一截 如图 总的动画为长度为2分钟零8秒 二 Button和对应事件 三 事件的代码 在Start 里面绑定 private void Awake myAnim animGo GetComponent
  • Flutter实现app自动升级

    话不多说 有过开发过移动应用的人都应该自动升级流程 首先获取本地应用版本 然后从服务器获取线上移动应用版本号作比较是否升级 第一步获取版本信息 API https pub dev packages package info 获取应用版本号
  • iview on-change用法

    原地址 https segmentfault com q 1010000011589626 iview框架select选择框on change事件如何返回当前选中的值 这是文档中的解释 on change 选中的Option变化时触发 默认
  • C++类与封装实例说明

    众所周知 C 具有三大特性 分别为封装 继承 多态 今天有位同学问到我应该如何去理解 我翻了翻笔记本 找到以前上课时学到的案例来解释 首先 成员函数存在希望公开或不希望公开的属性 这也构成了定义成员函数访问级别的三项 1 public 公开
  • 架构师--IT策略灵魂的创造者

    http blog csdn net aspop archive 2006 01 21 585823 aspx 在比尔 盖茨的众多称谓中 据说他更偏爱 首席软件架构师 同样 在网易创始人丁磊名字前 也有 首席架构师 这样的称谓 对于企业来说
  • IDEA国际化资源Key无法全局重命名的解决方案

    一 前言 最近在开发中使用到了HibernateValidator进行入参校验以及错误消息的国际化支持 大家应该都知道在使用HibernateValidator进行校验的时候 我们只需在需要在校验的变量上添加相应的注解 同时在message