当前位置: 首页 > news >正文

SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案

  • SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
    • 一、核心思路
    • 二、实现步骤
      • 1. 创建自定义注解 `@AmountFormat`
      • 2. 编写金额格式化拦截器
      • 3. 注册拦截器并配置拦截路径
      • 4. 在实体类字段上使用注解
    • 三、拦截器执行时机说明
    • 四、注意事项
    • 五、方案优势
    • 六、总结

SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案

在金融、电商等涉及金额的项目中,我们经常需要对BigDecimal类型的金额字段统一保留指定小数位数。如果在每个业务方法中手动调用setScale方法,会造成大量代码冗余,且难以统一维护。

本文将介绍一种基于SpringBoot 拦截器 + 自定义注解的方案,实现金额字段的自动格式化,让代码更简洁、更易维护。

一、核心思路

  1. 定义一个自定义注解@AmountFormat,用于标记需要格式化的金额字段,并支持指定小数位数。
  2. 编写一个拦截器AmountFormatInterceptor,在请求处理阶段,通过反射扫描被注解标记的字段。
  3. 对扫描到的BigDecimal类型字段,按照注解指定的小数位数进行格式化处理。
  4. 注册拦截器,配置拦截路径,实现全局生效。

二、实现步骤

1. 创建自定义注解@AmountFormat

该注解用于标记需要格式化的金额字段,支持通过scale属性指定小数位数,默认保留2位小数。

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/** * 金额格式化注解,用于标记需要统一处理小数位数的字段 */@Retention(RetentionPolicy.RUNTIME)// 注解在运行时生效,允许反射获取@Target(ElementType.FIELD)// 注解仅作用于类的字段public@interfaceAmountFormat{/** * 保留小数位数,默认2位 */intscale()default2;}

2. 编写金额格式化拦截器

拦截器实现HandlerInterceptor接口,在preHandle方法中完成核心逻辑:扫描目标类的字段,对被@AmountFormat标记的BigDecimal字段进行格式化。

importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.HandlerInterceptor;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.lang.reflect.Field;importjava.math.BigDecimal;importjava.math.RoundingMode;/** * 金额格式化拦截器,自动处理被@AmountFormat标记的字段 */publicclassAmountFormatInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{// 只处理 Controller 中的方法(HandlerMethod 类型)if(handlerinstanceofHandlerMethod){HandlerMethodhandlerMethod=(HandlerMethod)handler;// 获取目标类的实例ObjecttargetBean=handlerMethod.getBean();// 获取目标类的所有字段Field[]fields=targetBean.getClass().getDeclaredFields();for(Fieldfield:fields){// 判断字段是否被@AmountFormat注解标记if(field.isAnnotationPresent(AmountFormat.class)){// 设置私有字段可访问field.setAccessible(true);// 获取字段的值ObjectfieldValue=field.get(targetBean);// 仅处理BigDecimal类型的字段if(fieldValueinstanceofBigDecimal){AmountFormatannotation=field.getAnnotation(AmountFormat.class);intscale=annotation.scale();// 格式化金额:四舍五入,保留指定小数位数BigDecimalformattedValue=((BigDecimal)fieldValue).setScale(scale,RoundingMode.HALF_UP);// 将格式化后的值设置回字段field.set(targetBean,formattedValue);}}}}// 返回true,继续执行后续拦截器和Controller方法returntrue;}}

关键说明

  • preHandle方法在 Controller 方法执行前调用,保证格式化逻辑优先执行。
  • 通过反射获取字段值时,需要调用field.setAccessible(true)来访问私有字段。
  • 采用RoundingMode.HALF_UP模式进行四舍五入,符合日常金额计算的需求。

3. 注册拦截器并配置拦截路径

通过配置类WebConfig实现WebMvcConfigurer接口,注册拦截器并设置拦截范围。

importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * Web 配置类,用于注册拦截器 */@ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){// 注册金额格式化拦截器registry.addInterceptor(newAmountFormatInterceptor())// 拦截所有请求.addPathPatterns("/**")// 排除不需要拦截的路径(可选).excludePathPatterns("/static/**","/error");}}

4. 在实体类字段上使用注解

在需要格式化的BigDecimal类型金额字段上添加@AmountFormat注解,即可实现自动格式化。

importjava.math.BigDecimal;/** * 商品实体类 */publicclassProduct{privateLongid;privateStringproductName;// 金额字段:默认保留2位小数@AmountFormatprivateBigDecimalprice;// 金额字段:自定义保留3位小数@AmountFormat(scale=3)privateBigDecimaldiscountPrice;// 省略 getter/setter 方法}

三、拦截器执行时机说明

SpringMVC 拦截器有三个核心方法,各自的执行时机不同:

  1. preHandle:在 Controller 方法执行前调用。本文的格式化逻辑放在此方法,保证业务逻辑处理的是格式化后的金额。
  2. postHandle:在 Controller 方法执行后、视图渲染前调用。适合对处理结果进行二次加工。
  3. afterCompletion:在整个请求结束后调用。适合做资源清理等收尾工作。

四、注意事项

  1. 字段类型限制:拦截器仅对BigDecimal类型的字段生效,其他类型(如Double)不会处理。建议金额字段统一使用BigDecimal,避免精度丢失。
  2. 反射权限问题:必须调用field.setAccessible(true),否则无法访问实体类的私有字段,会抛出IllegalAccessException异常。
  3. 拦截路径配置:通过addPathPatternsexcludePathPatterns精准控制拦截范围,避免拦截静态资源、错误页面等不需要处理的请求。
  4. 四舍五入模式:本文使用RoundingMode.HALF_UP,如果业务需要其他舍入模式(如向下取整),可以在注解中新增属性配置。

五、方案优势

  1. 解耦性强:格式化逻辑与业务逻辑完全分离,无需在业务代码中重复编写setScale方法。
  2. 维护成本低:如果需要调整小数位数,只需修改注解的scale参数,无需改动大量业务代码。
  3. 全局生效:拦截器配置后,所有标记注解的字段都会自动格式化,实现统一管控。

六、总结

通过拦截器 + 自定义注解的组合,我们可以优雅地解决项目中金额字段格式化的问题。这种方案不仅减少了代码冗余,还提高了代码的可维护性,特别适合金融、电商等对金额精度要求高的项目。

在实际开发中,我们还可以基于此思路扩展更多功能,比如对日期字段的统一格式化、对敏感字段的脱敏处理等。

http://www.jsqmd.com/news/344439/

相关文章:

  • Vue 2.3
  • *Turnitin
  • 基于MATLAB的油润滑轴承压力分布求解
  • python学习一:变量python简单数据类型
  • 稀疏化压缩测试:神经架构搜索在模型精简的精度损失验证工具热度解析
  • 2026年遗产继承专业律师排名揭晓,冠腾律所李静律师口碑性价比双高 - 工业品牌热点
  • 《TAML》好文推荐 | 来自中国科学院力学研究所张磊博士 评估大语言模型在计算流体力学领域的知识利用、学习与创造
  • 深入解析:MySQL——增删改查操作
  • 空间智能 (Spatial Intelligence)
  • springboot基于Java的仓库管理系统(源码+文档+运行视频+讲解视频)
  • 基于 Starlight 文档站点接入 Microsoft Clarity 的完整实践指南
  • 建筑资质专业代办公司价格差异大天津广运达性价比高吗 - 工业设备
  • 2026年专业的喷绘喷印,写真喷印厂家实力推荐名录 - 品牌鉴赏师
  • 2026年阿里云Openclaw(clawdbot)秒级部署步骤
  • ‌碳信用计算工具:测试从业者如何用MLOps破解碳排放核算与交易‌
  • 横评后发现!王者级的一键生成论文工具 —— 千笔ai写作
  • 2026年回收手机价钱多少,哪种渠道更划算? - 京回收小程序
  • 2026灌流器厂家排名及发展趋势解析 - 品牌2025
  • springboot基于Java的茶叶销售商城系统(源码+文档+运行视频+讲解视频)
  • 深度测评9个降AI率网站,千笔·专业降AI率智能体解决论文AIGC检测难题
  • 肾病领域灌流器详解及相关厂家介绍 - 品牌2025
  • springboot基于java的餐厅美食信息管理系统(源码+文档+运行视频+讲解视频)
  • [Linux]学习笔记系列 -- [drivers][mmc]mmc_sd
  • 腾讯云Lighthouse 一键部署 OpenClaw 转化为专属股市分析师实战教程
  • 智能体
  • Linux 系统 定期更新硬件时钟(RTC)
  • 解决ORA-28002: the password will expire within 7 days
  • 解决程序连不上RabbitMQ:Attempting to connect to/access to vhost虚拟主机挂了的排错与恢复
  • 2026肝衰竭人工肝耗材优选健帆生物 - 品牌2025
  • 江西化学制品企业 EcoVadis 铜牌认证成功案例 —— 奋飞咨询助力可持续发展跃升 - 奋飞咨询ecovadis