溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換

發(fā)布時間:2020-12-10 13:43:29 來源:億速云 閱讀:407 作者:Leah 欄目:開發(fā)技術(shù)

這篇文章給大家介紹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 {

}

2、YuanToFenRequestBodyAdvice.java

實現(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<&#63; extends HttpMessageConverter<&#63;>> converterType) {
    return methodParameter.hasParameterAnnotation(RequestBody.class);
  }

  @Override
  public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<&#63; extends HttpMessageConverter<&#63;>> converterType) {
    if(body == null) {
      return null;
    }

    Class<&#63;> 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<&#63;> 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

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

YuanToFen.java

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface YuanToFen {

}

4、FenToYuanResponseBodyAdvice.java

當 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<&#63;> 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<&#63;> 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)元這兩個功能。

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());
    }
  }

}

6、Order.java

實體類,用于接收請求對象以及響應測試金額轉(zhuǎn)換。

Order.java

@Data
public class Order {

  private String orderId;

  private String productName;

  @FenToYuan
  @YuanToFen
  private BigDecimal orderAmount;

}

7、OrderController.java

訂單控制類,提供了兩個方法:訂單創(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;
  }

}

8、測試

使用工具 Postman 發(fā)送 http 進行功能測試。

8.1 元轉(zhuǎn)分測試

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

Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換

控制臺打印如下:

Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換

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

8.2 測試分轉(zhuǎn)元

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

Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換

這個時候得到訂單金額為 10 元。查詢訂單的邏輯如下:

Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換

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

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

關(guān)于Spring Boot中的貨幣單位怎么利用Mvc 擴展進行轉(zhuǎn)換就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(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)容。

AI