日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
SpringBoot使用轉(zhuǎn)換器將前端參數(shù)轉(zhuǎn)換為枚舉

前言

最近遇到一個小伙伴問前端枚舉轉(zhuǎn)換問題,才意識到可以通過轉(zhuǎn)換器(Converter)自動將前端傳入的字段值使用枚舉接收。

我自己搗鼓了一番,現(xiàn)在記錄筆記分享一下!有興趣的小伙伴可以自己嘗試一下!

這里使用的是 MyBatis-Plus 和 SpringBoot 2.3.4.RELEASE

1實現(xiàn)過程

配置轉(zhuǎn)換器

 
 
 
 
  1. /**
  2.  * @author liuzhihang
  3.  * @date 2021/8/31 16:29
  4.  */
  5. @Configuration
  6. public class WebConfig implements WebMvcConfigurer {
  7.     @Override
  8.     public void addFormatters(FormatterRegistry registry) {
  9.         registry.addConverterFactory(new ConverterFactory() {
  10.             @Override
  11.             public  Converter getConverter(Class targetType) {
  12.                 T[] enums = targetType.getEnumConstants();
  13.                 return source -> {
  14.                     for (T e : enums) {
  15.                         if (e.getCode().equals(source)) {
  16.                             return e;
  17.                         }
  18.                     }
  19.                     throw new IllegalArgumentException("枚舉 Code 不正確");
  20.                 };
  21.             }
  22.         });
  23.     }
  24. }

直接在 WebMvcConfigurer 里實現(xiàn) addFormatters 方法即可,然后 new 一個 ConverterFactory。

WebMvcConfigurer 相信大家都不陌生,一般添加一些攔截器,通用校驗 token、日志等等都會用到。具體可以參考這篇文章:幾行代碼輕松實現(xiàn)跨系統(tǒng)傳遞 traceId,再也不用擔(dān)心對不上日志了!,里面有一些其他的應(yīng)用。

就這些,很簡單的實現(xiàn)。下面介紹下項目的內(nèi)容和代碼,方便理解。

項目代碼

  • 請求參數(shù):
 
 
 
 
  1. POST http://localhost:8818/user/listByStatus
  2. Content-Type: application/json
  3. {
  4.   "orderStatus": 1
  5. }
  • Controller
 
 
 
 
  1. /**
  2.  * @author liuzhihang
  3.  * @date 2021/8/30 11:08
  4.  */
  5. @Slf4j
  6. @RestController
  7. @RequestMapping("/user")
  8. public class UserController {
  9.     @Autowired
  10.     private OrderService orderService;
  11.     @PostMapping(value = "/listByStatus")
  12.     public ResultVO listByStatus(@Validated @RequestBody UserRequest request)  {
  13.         log.info("請求參數(shù):{}", request);
  14.         List orderList = orderService.getByOrderStatus(request.getOrderStatus());
  15.         UserResponse response = new UserResponse();
  16.         response.setRecords(orderList);
  17.         log.info("返回參數(shù):{}", response);
  18.         return ResultVO.success(response);
  19.     }
  20. }
  • Entity
 
 
 
 
  1. @Data
  2. public class UserRequest {
  3.     private OrderStatusEnum orderStatus;
  4.     private ViewStatusEnum viewStatus;
  5. }
  6. @Data
  7. public class UserResponse {
  8.     private List records;
  9. }

Web 傳入 orderStatus 為 1,而后端接收對象是 UserRequest 的 orderStatus 字段是個 OrderStatusEnum 類型的枚舉。

這里就需要自動將數(shù)字類型的字段轉(zhuǎn)換為枚舉字段。這個枚舉會直接通過 MyBatis-Plus 查詢。

為什么要這么用呢?

其實原因很簡單,使用枚舉限制數(shù)據(jù)庫字段的類型,比如數(shù)據(jù)庫狀態(tài)只有 0、1、2,那就和代碼里的枚舉對應(yīng)起來。防止傳入其他值。

  • 枚舉
 
 
 
 
  1. public interface BaseEnum {
  2.     Object getCode();
  3. }
 
 
 
 
  1. public enum OrderStatusEnum implements BaseEnum {
  2.     INIT(0, "初始狀態(tài)"),
  3.     SUCCESS(1, "成功"),
  4.     FAIL(2, "失敗");
  5.     @EnumValue
  6.     @JsonValue
  7.     private final int code;
  8.     private final String desc;
  9.     OrderStatusEnum(int code, String desc) {
  10.         this.code = code;
  11.         this.desc = desc;
  12.     }
  13.     @Override
  14.     public Integer getCode() {
  15.         return code;
  16.     }
  17.     public String getDesc() {
  18.         return desc;
  19.     }
  20. }

這里先聲明接口 BaseEnum,所有的枚舉都繼承這個接口,并實現(xiàn) getCode 方法。

@EnumValue:MyBatis-Plus 的枚舉,和數(shù)據(jù)庫字段映射用的

@JsonValue:返回給前端時,這個枚舉字段序列化時,返回參數(shù)只顯示 code。

這樣就可以實現(xiàn)效果,請求參數(shù)為數(shù)字,接收對象字段為枚舉,返回字段也是 code。

效果

測試結(jié)果

測試結(jié)果經(jīng)過驗證,是可以勝任傳入數(shù)值和字符串的。

也可以結(jié)合異常處理器,返回通用異常。具體怎么用查一查 @ExceptionHandler 就知道了。

具體說明

在 addFormatters 方法中可以看到 registry.addConverterFactory() 接收的是一個 ConverterFactory 對象。

 
 
 
 
  1. public interface ConverterFactory {
  2.   Converter getConverter(Class targetType);
  3. }
  • S 就是傳入的字段類型(數(shù)字,字符串)
  • R 是要轉(zhuǎn)換為的類型(枚舉)
  • T 繼承了 R,其實就是參數(shù)對象中字段的類型

在 ConverterFactory 的 getConverter 方法則需要返回一個實際的轉(zhuǎn)換器 Converter

 
 
 
 
  1. @FunctionalInterface
  2. public interface Converter {
  3.  @Nullable
  4.  T convert(S source);
  5. }

convert 方法的入?yún)⑹且粋€ source,就是要轉(zhuǎn)換為什么類型的,這里就是數(shù)字/字符串,然后返回一個枚舉即可。

注意這里加了 @FunctionalInterface 就意味著這里是可以用 lambda 表達(dá)式的。

2優(yōu)化

一般 WebConfig 中除了實現(xiàn) addFormatters 方法外,還會實現(xiàn) addInterceptors 等等,這樣寫難免會很長,所以可以改為下面這種。

 
 
 
 
  1. @Configuration
  2. public class WebConfig implements WebMvcConfigurer {
  3.     @Autowired
  4.     private LogInterceptor logInterceptor;
  5.     @Autowired
  6.     private AppTokenInterceptor appTokenInterceptor;
  7.     @Autowired
  8.     private EnumConverterFactory enumConverterFactory;
  9.     @Override
  10.     public void addInterceptors(InterceptorRegistry registry) {
  11.         // 日志
  12.         registry.addInterceptor(logInterceptor)
  13.                 .addPathPatterns("/**");
  14.         // app token校驗
  15.         registry.addInterceptor(appTokenInterceptor)
  16.                 .addPathPatterns("/app/**");
  17.     }
  18.     @Override
  19.     public void addFormatters(FormatterRegistry registry) {
  20.         
  21.         // 枚舉轉(zhuǎn)換
  22.         registry.addConverterFactory(enumConverterFactory);
  23.     }
  24. }

這種就需要咱們創(chuàng)建 EnumConverterFactory 類并實現(xiàn) ConverterFactory 接口了,還得注入到 Spring 容器中

 
 
 
 
  1. @Component
  2. public class EnumConverterFactory implements ConverterFactory {
  3.     @Override
  4.     public  Converter getConverter(Class targetType) {
  5.         return new EnumConverter<>(targetType);
  6.     }
  7. }
  8. public class EnumConverter implements Converter {
  9.     private final Class targetType;
  10.     public EnumConverter(Class targetType) {
  11.         this.targetType = targetType;
  12.     }
  13.     @Override
  14.     public T convert(Object source) {
  15.         for (T e : targetType.getEnumConstants()) {
  16.             if (e.getCode().equals(source)) {
  17.                 return e;
  18.             }
  19.         }
  20.         throw new IllegalArgumentException("枚舉 Code 不正確");
  21.     }
  22. }

3總結(jié)

當(dāng)然這里也有一些其他的優(yōu)化點,比如可以使用緩存將 Convert 緩存起來。

不過我也遇到一個其他的問題,就是我 debug 斷點竟然一直沒有斷到轉(zhuǎn)換器中,不知道有沒有小伙伴嘗試過?


網(wǎng)站欄目:SpringBoot使用轉(zhuǎn)換器將前端參數(shù)轉(zhuǎn)換為枚舉
文章出自:http://m.5511xx.com/article/djhchjs.html