久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術(shù)文章
文章詳情頁

Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解

瀏覽:93日期:2023-07-28 18:44:17

由于公司是支付平臺(tái),所以很多項(xiàng)目都涉及到金額,業(yè)務(wù)方轉(zhuǎn)遞過來的金額是單位是元,而我們數(shù)據(jù)庫保存的金額單位是分。一般金額的流向有以下幾個(gè)方向:

外部業(yè)務(wù)方請(qǐng)求我們服務(wù),傳遞過來的金額單位是元,需要把元轉(zhuǎn)換成分。比如:下單接口。 內(nèi)部系統(tǒng)之間的流轉(zhuǎn),不管是向下傳遞還是向上傳遞系統(tǒng)間的流程都是分,不需要扭轉(zhuǎn)。比如:調(diào)用支付引擎(向下傳遞),支付引擎回調(diào)收單業(yè)務(wù)(向上傳遞)。 向業(yè)務(wù)方返回?cái)?shù)據(jù),這個(gè)時(shí)候需要把分轉(zhuǎn)換成元。比如:商戶調(diào)用查詢訂單接口。 內(nèi)部系統(tǒng)的展示,這個(gè)時(shí)候需要把分轉(zhuǎn)換成元。比如:顯示收入金額的報(bào)表。

如果我們對(duì)于請(qǐng)求參數(shù)是金額類型的參數(shù)逐一處理,這樣重復(fù)的操作就會(huì)顯得相當(dāng)?shù)牟粌?yōu)雅。對(duì)于請(qǐng)求參數(shù)我們可以使用 Spring MVC 提供的擴(kuò)展擴(kuò)展。對(duì)于金額操作我們可以分為:

業(yè)務(wù)方傳入金額單位為元,需要把業(yè)務(wù)方傳入的元轉(zhuǎn)換成分,可以使用 Spring MVC Restful 請(qǐng)求參數(shù)擴(kuò)展 RequestBodyAdvice 接口。 業(yè)務(wù)方需要查詢數(shù)據(jù),需要把數(shù)據(jù)庫保存的分轉(zhuǎn)換成元,可以使用 Spring MVC Restful 響應(yīng)參數(shù)擴(kuò)展 ResponseBodyAdvice 接口。

下面我們就來看一下代碼實(shí)現(xiàn)。

1、FenToYuan.java

定義一個(gè)標(biāo)注注解,用于標(biāo)注到需要把元轉(zhuǎn)換成分的 BigDecimal 類型的參數(shù)上面。

FenToYuan.java

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface FenToYuan {}2、YuanToFenRequestBodyAdvice.java

實(shí)現(xiàn) Spring MVC Restful 請(qǐng)求參數(shù)擴(kuò)展類,如果請(qǐng)求參數(shù)標(biāo)注了 @RequestBody 注解,并且請(qǐng)求參數(shù)的字段類型為 BigDecimal 就會(huì)把傳入的參數(shù)由元轉(zhuǎn)換成分。

YuanToFenRequestBodyAdvice.java

@Slf4j@ControllerAdvicepublic class YuanToFenRequestBodyAdvice extends RequestBodyAdviceAdapter { @Override public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { return methodParameter.hasParameterAnnotation(RequestBody.class); } @Override public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { if(body == null) { return null; } Class<?> clazz = body.getClass(); PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(clazz); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { String name = propertyDescriptor.getName(); if('class'.equals(name)){continue; } Field field = ReflectionUtils.findField(clazz, name); Class<?> fieldClazz = field.getType(); if(!fieldClazz.equals(BigDecimal.class) ){continue; } if(!field.isAnnotationPresent(YuanToFen.class)) {continue; } Method readMethod = propertyDescriptor.getReadMethod(); Method writeMethod = propertyDescriptor.getWriteMethod(); try {BigDecimal yuanAmount = (BigDecimal) readMethod.invoke(body);BigDecimal fenAmount = AmountUtils.yuan2Fen(yuanAmount);writeMethod.invoke(body, fenAmount); } catch (Exception e) {log.error('amount convert yuan to fen fail', e); } } return super.afterBodyRead(body, inputMessage, parameter, targetType, converterType); }}3、YuanToFen.java

標(biāo)注注解,當(dāng)響應(yīng)參數(shù)需要由分轉(zhuǎn)換成元的時(shí)候,就標(biāo)注這個(gè)注解。響應(yīng)值就會(huì)把數(shù)據(jù)庫或者下游傳遞過來的金額為分的參數(shù)轉(zhuǎn)換成元。

YuanToFen.java

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface YuanToFen {}4、FenToYuanResponseBodyAdvice.java

當(dāng) Spring MVC 方法上標(biāo)注了 ResponseBody 或者類上標(biāo)注了 RestController 注解時(shí),如果響應(yīng)對(duì)象的 BigDecimal 標(biāo)注了 @YuanToFen 注解就會(huì)進(jìn)行金額分轉(zhuǎn)換成元。

FenToYuanResponseBodyAdvice.java

@Slf4j@ControllerAdvicepublic class FenToYuanResponseBodyAdvice implements ResponseBodyAdvice { @Override public boolean supports(MethodParameter returnType, Class converterType) { return returnType.hasParameterAnnotation(ResponseBody.class)|| returnType.getDeclaringClass().isAnnotationPresent(RestController.class); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if(body == null) { return null; } Class<?> clazz = body.getClass(); PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(clazz); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { String name = propertyDescriptor.getName(); if('class'.equals(name)){continue; } Field field = ReflectionUtils.findField(clazz, name); Class<?> fieldClazz = field.getType(); if(!fieldClazz.equals(BigDecimal.class) ){continue; } if(!field.isAnnotationPresent(FenToYuan.class)) {continue; } Method readMethod = propertyDescriptor.getReadMethod(); Method writeMethod = propertyDescriptor.getWriteMethod(); try {BigDecimal fenAmount = (BigDecimal) readMethod.invoke(body);BigDecimal yuanAmount = AmountUtils.fen2yuan(fenAmount);writeMethod.invoke(body, yuanAmount); } catch (Exception e) {log.error('amount convert fen to yuan fail', e); } } return body; }}5、AmountUtils.java

金錢工具類,提供了金錢的元轉(zhuǎn)分以及分轉(zhuǎn)元這兩個(gè)功能。

AmountUtils.java

public abstract class AmountUtils { /** * 金額單位元轉(zhuǎn)分 */ public static BigDecimal yuan2Fen(BigDecimal amount) { if (amount == null) { return BigDecimal.ZERO; } return amount.movePointRight(2).setScale(0, BigDecimal.ROUND_DOWN); } /** * 金額單位分轉(zhuǎn)元 */ public static BigDecimal fen2yuan(BigDecimal amount) { return null2Zero(amount).movePointLeft(2).setScale(2, BigDecimal.ROUND_HALF_UP); } /** * 把 null 當(dāng)作 0 處理 */ public static BigDecimal null2Zero(Number amount) { if (amount == null) { return BigDecimal.ZERO; } if (amount instanceof BigDecimal) { return (BigDecimal) amount; } else { return new BigDecimal(amount.toString()); } }}6、Order.java

實(shí)體類,用于接收請(qǐng)求對(duì)象以及響應(yīng)測(cè)試金額轉(zhuǎn)換。

Order.java

@Datapublic class Order { private String orderId; private String productName; @FenToYuan @YuanToFen private BigDecimal orderAmount;}7、OrderController.java

訂單控制類,提供了兩個(gè)方法:訂單創(chuàng)建(/order/apply)標(biāo)注了 @RequestBody,會(huì)把傳入的金額由元轉(zhuǎn)換成分,然后打印到控制臺(tái)。訂單查詢(order/query) 聲明方法的類上標(biāo)注了 @RestController ,通過關(guān)鍵字 new 創(chuàng)建一個(gè)訂單金額為 1000 分的訂單。

OrderController.java

@RestController@RequestMapping('order')public class OrderController { @RequestMapping('apply') public void apply(@RequestBody Order order) { System.out.println(JSON.toJSONString(order)); } @RequestMapping('query/{id}') public Order query(@PathVariable String id) { Order order = new Order(); order.setOrderId(id); order.setOrderAmount(new BigDecimal('1000')); order.setProductName('test'); return order; }}8、測(cè)試

使用工具 Postman 發(fā)送 http 進(jìn)行功能測(cè)試。

8.1 元轉(zhuǎn)分測(cè)試

通過 postman 請(qǐng)求 http:localhost:8080/order/apply發(fā)送以下請(qǐng)求:

Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解

控制臺(tái)打印如下:

Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解

業(yè)務(wù)方傳入金額為 1 元,控制臺(tái)打印的結(jié)果是 100 分。

8.2 測(cè)試分轉(zhuǎn)元

通過 postman 請(qǐng)求 http:localhost:8080/order/query/1發(fā)送以下請(qǐng)求:

Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解

這個(gè)時(shí)候得到訂單金額為 10 元。查詢訂單的邏輯如下:

Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解

這個(gè)時(shí)候訂單的金額是 1000 分,轉(zhuǎn)換成 10 元完成了我們的目標(biāo)功能。

當(dāng)然這種方式是有一個(gè)缺陷的,就是它不能遞歸的進(jìn)行金額轉(zhuǎn)換,后面可以借鑒 Hibernate 的遞歸校驗(yàn)邏輯來進(jìn)行遞歸金額參數(shù)的轉(zhuǎn)換。

到此這篇關(guān)于Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)Spring Boot貨幣單位轉(zhuǎn)換內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 国产剧情一区二区 | 蜜桃av一区 | 亚洲精品一区久久久久久 | 国产日韩一区 | www.国产91 | www精品| 国产在线一区二区 | 91社区影院| 国产精品久久久久久久久久免费 | 国产婷婷精品 | 国产精品久久久久久久7电影 | 亚洲 欧美 精品 | 国产玖玖 | 日韩一区二区三区在线观看 | 最近的中文字幕在线看视频 | 国产精品久久久久久久久 | 久久精品系列 | 国产精品久久久久久久午夜片 | 久久久xx | 91啪影院| av中文字幕在线播放 | 国产精品白浆 | 亚洲欧美日韩电影 | www操com| 国产精品久久久久久久久久免费看 | 成人亚洲区 | 久久久av | 日本一区二区不卡 | 黄色国产大片 | av片在线免费观看 | 国产v日产∨综合v精品视频 | 亚洲一级毛片 | 国产艳妇av视国产精选av一区 | 欧美日韩亚洲视频 | 国产成人免费 | 国产精自产拍久久久久久 | 伊人av成人 | 午夜在线电影 | 狠狠色狠狠色合久久伊人 | 在线99热 | 欧美aaa视频|