您好,登錄后才能下訂單哦!
這篇文章給大家介紹Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
1、FenToYuan.java
定義一個標注注解,用于標注到需要把元轉(zhuǎn)換成分的 BigDecimal
類型的參數(shù)上面。
FenToYuan.java
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FenToYuan { }
實現(xiàn) Spring MVC Restful 請求參數(shù)擴展類,如果請求參數(shù)標注了 @RequestBody
注解,并且請求參數(shù)的字段類型為 BigDecimal
就會把傳入的參數(shù)由元轉(zhuǎn)換成分。
YuanToFenRequestBodyAdvice.java
@Slf4j @ControllerAdvice public 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); } }
標注注解,當響應參數(shù)需要由分轉(zhuǎn)換成元的時候,就標注這個注解。響應值就會把數(shù)據(jù)庫或者下游傳遞過來的金額為分的參數(shù)轉(zhuǎn)換成元。
YuanToFen.java
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface YuanToFen { }
當 Spring MVC 方法上標注了 ResponseBody
或者類上標注了 RestController
注解時,如果響應對象的 BigDecimal
標注了 @YuanToFen
注解就會進行金額分轉(zhuǎn)換成元。
FenToYuanResponseBodyAdvice.java
@Slf4j @ControllerAdvice public 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; } }
金錢工具類,提供了金錢的元轉(zhuǎn)分以及分轉(zhuǎn)元這兩個功能。
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 當作 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()); } } }
實體類,用于接收請求對象以及響應測試金額轉(zhuǎn)換。
Order.java
@Data public class Order { private String orderId; private String productName; @FenToYuan @YuanToFen private BigDecimal orderAmount; }
訂單控制類,提供了兩個方法:訂單創(chuàng)建(/order/apply)標注了 @RequestBody
,會把傳入的金額由元轉(zhuǎn)換成分,然后打印到控制臺。訂單查詢(order/query) 聲明方法的類上標注了 @RestController
,通過關(guān)鍵字 new
創(chuàng)建一個訂單金額為 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; } }
使用工具 Postman 發(fā)送 http 進行功能測試。
8.1 元轉(zhuǎn)分測試
通過 postman 請求 http:localhost:8080/order/apply
發(fā)送以下請求:
控制臺打印如下:
業(yè)務方傳入金額為 1 元,控制臺打印的結(jié)果是 100 分。
8.2 測試分轉(zhuǎn)元
通過 postman 請求 http:localhost:8080/order/query/1
發(fā)送以下請求:
這個時候得到訂單金額為 10 元。查詢訂單的邏輯如下:
這個時候訂單的金額是 1000 分,轉(zhuǎn)換成 10 元完成了我們的目標功能。
當然這種方式是有一個缺陷的,就是它不能遞歸的進行金額轉(zhuǎn)換,后面可以借鑒 Hibernate 的遞歸校驗邏輯來進行遞歸金額參數(shù)的轉(zhuǎn)換。
關(guān)于Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。