news 2026/4/30 12:46:07

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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. 全局生效:拦截器配置后,所有标记注解的字段都会自动格式化,实现统一管控。

六、总结

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/28 0:27:07

*QuillBot

QuillBot是一款集合了多种功能的AI文字处理工具包,主要帮助用户优化英文写作。它就像一套智能的文字处理工具,可以帮你调整句子、检查错误、提炼重点。 一、它是什么 QuillBot的核心是一个AI驱动的文本改写和优化引擎。你可以把它理解为一个功能丰富的…

作者头像 李华
网站建设 2026/4/29 17:28:21

例说FPGA:可直接用于工程项目的第一手经验【2.9】

12.7 Verilog代码解析 本实例分为4个层级,大大小小共计25个模块,其层次结构如图12-27所示。 各个模块的基本功能定义如表12-2所示。 表12-2 Verilog各个模块功能描述 1.vip.v模块代码解析 略。 2.sys_ctrl.v模块代码解析 略,请参考例程工程实例1。 3.ddr2_controlle…

作者头像 李华
网站建设 2026/4/25 14:25:28

SEW变频器MCH42A0370-503-4-0T 08271682

SEW变频器 MCH42A0370-503-4-0T 08271682 详细介绍1. 概述SEW-Eurodrive是全球领先的驱动技术解决方案供应商之一,其产品广泛应用于工业自动化、物料输送、仓储物流等诸多领域。MCH系列变频器是SEW旗下重要的产品线之一,专为控制交流异步电动机而设计。型…

作者头像 李华
网站建设 2026/4/27 20:41:05

基于Java的建筑工程合同智慧管理系统的设计与实现全方位解析:附毕设论文+源代码

1. 为什么这个毕设项目值得你 pick ? 建筑工程合同智慧管理系统采用Java语言开发,基于SpringMVC框架和MySQL数据库构建。该系统涵盖了项目管理、合同管理、结算审计等10个主要功能模块,满足普通员工的数据录入与查阅需求及部门领导的审核与统计分析职责…

作者头像 李华