色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

Spring:如何使用枚舉參數

瀏覽:51日期:2023-06-25 18:48:34
目錄 枚舉參數確認需求定義枚舉Converter 和 ConverterFactory加載配置測試總結 枚舉參數

接口開發過程中不免有表示類型的參數,比如 0 表示未知,1 表示男,2 表示女。通常有兩種做法,一種是用數字表示,另一種是使用枚舉實現。

使用數字表示就是通過契約形式,約定每個數字表示的含義,接口接收到參數,就按照約定對類型進行判斷,接口維護成本比較大。

在 Spring 體系中,使用枚舉表示,是借助 Spring 的 Converter 機制,可以將數字或字符串對應到枚舉的序號或者 name,然后將前端的輸入轉換為枚舉類型。

在場景不復雜的場景中,枚舉可以輕松勝任。

于是,迅速實現邏輯,準備提測。這個時候需求變了,不允許選擇未知性別,只能選男或女,就沒有 0 值。這樣,因為取值是從 1 開始,而枚舉的序號是從 0 開始,就會產生沖突。

還有一些不太多的場景,就是前端不期望類型都是用數字,可能期望用一些有意義的字符串表示。但是按照前端規范,需要用小寫或者駝峰命名。但是后端的規范中,枚舉必須是大寫,又是沖突。

需求合不合理暫且不論,我們要保存對技術的探索精神。

確認需求

首先確認需求。我們期望定義一個枚舉類作為參數,接口訪問的時候,可以是 int 類型的 id,id 取值不限于枚舉的序號;也可以是 String 類型的 code,code 取值不限于枚舉的 name。換句話說,這個枚舉有個 id 和 code,隨意定義,只要接口傳過來匹配上,就能夠自動轉成枚舉類型。

既然這樣,我們就規范下 id 和 code 取值。為了擴展,定義三個接口:IdBaseEnum、CodeBaseEnum 以及 IdCodeBaseEnum。

public interface IdBaseEnum { Integer getId();}public interface CodeBaseEnum { String getCode();}public interface IdCodeBaseEnum extends IdBaseEnum, CodeBaseEnum {}

接下來就該定義我們的主角了。

定義枚舉

前面定義了三個接口,分別是單獨 id、單獨 code,和有 id 和 code 的。這樣,我們就可以定義三種枚舉,分別對應三個接口。三種方式類似,所以就不在文中重復列舉了。感興趣的可以關注公眾號「看山的小屋」回復 spring 獲取源碼。

我們定義一個性別枚舉,枚舉包含 id 和 code 兩個屬性。

public enum GenderIdCodeEnum implements IdCodeBaseEnum { MALE(1, 'male'), FEMALE(2, 'female'); private final Integer id; private final String code; GenderIdCodeEnum(Integer id, String code) {this.id = id;this.code = code; } @Override public String getCode() {return code; } @Override public Integer getId() {return id; }}

這里需要注意一點,id 和 code 不能重復。

1.id 與 id、code 與 code 不能重復,比如 MAIL 定義 id 是 1,FAMLE 就不能定義 id 是 1 了。

2.id 與 code 之間也不能重復,比如,MALE 定義 id 是 1001,FEMALE 定義 code 是 1001。

這是由于 Spring 在轉換參數的時候,將輸入參數全部視為 String 類型。雖然我們定義 id 和 code 類型不同,但是在匹配的時候,都是按照字符串匹配的。如果存在相同值,就會產生歧義。

Converter 和 ConverterFactory

根據規范,接下來定義一下 Converter 和 ConverterFactory。這些是 Spring 留給我們的擴展口,按照規范定義即可。

Converter 類:

public class IdCodeToEnumConverter<T extends IdCodeBaseEnum> implements Converter<String, T> { private final Map<String, T> idEnumMap = Maps.newHashMap(); private final Map<String, T> codeEnumMap = Maps.newHashMap(); public IdCodeToEnumConverter(Class<T> enumType) {Arrays.stream(enumType.getEnumConstants()).forEach(x -> { idEnumMap.put(x.getId().toString(), x); codeEnumMap.put(x.getCode(), x);}); } @Override public T convert(String source) {return Optional.of(source).map(codeEnumMap::get).orElseGet(() -> Optional.of(source).map(idEnumMap::get).orElseThrow(() -> new CodeBaseException(ErrorResponseEnum.PARAMS_ENUM_NOT_MATCH))); }}

ConverterFactory 類:

public class IdCodeToEnumConverterFactory implements ConverterFactory<String, IdCodeBaseEnum> { @SuppressWarnings('rawtypes') private static final Map<Class, Converter> CONVERTERS = Maps.newHashMap(); @Override public <T extends IdCodeBaseEnum> Converter<String, T> getConverter(Class<T> targetType) {//noinspection uncheckedConverter<String, T> converter = CONVERTERS.get(targetType);if (converter == null) { converter = new IdCodeToEnumConverter<>(targetType); CONVERTERS.put(targetType, converter);}return converter; }}

這兩個就是轉換的核心了,我們只要將他們裝配到 Spring 的類型轉換器中,就能夠實現枚舉類型的自動轉化了。

加載配置

將我們定義的 Converter 和 ConverterFactory 注冊到 Spring 的類型轉換器中。

@Configurationpublic class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) {registry.addConverterFactory(new IdCodeToEnumConverterFactory());registry.addConverterFactory(new CodeToEnumConverterFactory());registry.addConverterFactory(new IdToEnumConverterFactory()); }}

至此,核心定義全部結束。

測試

寫一個 Controller 作為測試入口:

@RestController@RequestMapping('echo')public class EchoController { @GetMapping('gender-id-code') public String genderIdCode(@RequestParam('gender') GenderIdCodeEnum gender) {return gender.name(); }}

準備測試用例測試:

@SpringBootTest(classes = SpringEnumParamApplication.class)@AutoConfigureMockMvcclass EchoControllerTest { @Autowired private MockMvc mockMvc; @ParameterizedTest @ValueSource(strings = {'MALE', 'male', '1'}) void genderIdCode(String gender) throws Exception {final String result = mockMvc.perform(MockMvcRequestBuilders.get('/echo/gender-id-code').param('gender', gender)).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn().getResponse().getContentAsString();Assertions.assertEquals('MALE', result); }}總結

實現枚舉參數并不難,只要按照 Spring 的擴展規范實現即可。需要注意的是,注意枚舉類中唯一的 id 和 code。

本文是應用,下篇說一下原理。以及 http body 形式請求的枚舉轉換邏輯。

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注好吧啦網的更多內容!

標簽: Spring
相關文章:
主站蜘蛛池模板: 久久免费播放 | 久久青草免费线观最新 | 99久久精品毛片免费播放 | 欧美日韩加勒比一区二区三区 | 欧美日韩精品一区二区视频在线观看 | 蜜臀91精品国产高清在线观看 | 99精品国产免费久久国语 | 欧美中文字幕在线视频 | 波多野结衣在线不卡 | 亚洲精品高清在线观看 | 成年人在线观看免费 | 99re热精品视频国产免费 | 国产第二页 | 久久国产精品一区二区三区 | 久久香蕉国产线看免费 | 欧美一区欧美二区 | 免费aa在线观看 男人的天堂 | 欧美理论在线 | 欧美视频区 | 日韩亚洲成a人片在线观看 日韩亚洲精品不卡在线 | 欧美精品综合一区二区三区 | 国产一级视频久久 | 91精品手机国产露脸 | 精品国产成人高清在线 | 一级毛片在线视频 | 午夜一级做a爰片久久毛片 午夜伊人网 | 一级一级一片免费高清 | 中文一级国产特级毛片视频 | 午夜精品网 | 波多野吉衣 免费一区 | 国产中文字幕在线播放 | 国产亚洲精品一品区99热 | 国产精品国产三级在线高清观看 | 日本三级网站 | 免费国产成人综合 | 国产亚洲精品久久 | 洋老外米糕国产一区二区 | 精品国产品国语在线不卡丶 | 欧美一级三级在线观看 | 收集最新中文国产中文字幕 | 九九九九在线视频播放 |