日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

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

Spring:如何使用枚舉參數(shù)

瀏覽:122日期:2023-06-25 18:48:34
目錄 枚舉參數(shù)確認(rèn)需求定義枚舉Converter 和 ConverterFactory加載配置測(cè)試總結(jié) 枚舉參數(shù)

接口開(kāi)發(fā)過(guò)程中不免有表示類型的參數(shù),比如 0 表示未知,1 表示男,2 表示女。通常有兩種做法,一種是用數(shù)字表示,另一種是使用枚舉實(shí)現(xiàn)。

使用數(shù)字表示就是通過(guò)契約形式,約定每個(gè)數(shù)字表示的含義,接口接收到參數(shù),就按照約定對(duì)類型進(jìn)行判斷,接口維護(hù)成本比較大。

在 Spring 體系中,使用枚舉表示,是借助 Spring 的 Converter 機(jī)制,可以將數(shù)字或字符串對(duì)應(yīng)到枚舉的序號(hào)或者 name,然后將前端的輸入轉(zhuǎn)換為枚舉類型。

在場(chǎng)景不復(fù)雜的場(chǎng)景中,枚舉可以輕松勝任。

于是,迅速實(shí)現(xiàn)邏輯,準(zhǔn)備提測(cè)。這個(gè)時(shí)候需求變了,不允許選擇未知性別,只能選男或女,就沒(méi)有 0 值。這樣,因?yàn)槿≈凳菑?1 開(kāi)始,而枚舉的序號(hào)是從 0 開(kāi)始,就會(huì)產(chǎn)生沖突。

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

需求合不合理暫且不論,我們要保存對(duì)技術(shù)的探索精神。

確認(rèn)需求

首先確認(rèn)需求。我們期望定義一個(gè)枚舉類作為參數(shù),接口訪問(wèn)的時(shí)候,可以是 int 類型的 id,id 取值不限于枚舉的序號(hào);也可以是 String 類型的 code,code 取值不限于枚舉的 name。換句話說(shuō),這個(gè)枚舉有個(gè) id 和 code,隨意定義,只要接口傳過(guò)來(lái)匹配上,就能夠自動(dòng)轉(zhuǎn)成枚舉類型。

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

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

接下來(lái)就該定義我們的主角了。

定義枚舉

前面定義了三個(gè)接口,分別是單獨(dú) id、單獨(dú) code,和有 id 和 code 的。這樣,我們就可以定義三種枚舉,分別對(duì)應(yīng)三個(gè)接口。三種方式類似,所以就不在文中重復(fù)列舉了。感興趣的可以關(guān)注公眾號(hào)「看山的小屋」回復(fù) spring 獲取源碼。

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

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

這里需要注意一點(diǎn),id 和 code 不能重復(fù)。

1.id 與 id、code 與 code 不能重復(fù),比如 MAIL 定義 id 是 1,F(xiàn)AMLE 就不能定義 id 是 1 了。

2.id 與 code 之間也不能重復(fù),比如,MALE 定義 id 是 1001,F(xiàn)EMALE 定義 code 是 1001。

這是由于 Spring 在轉(zhuǎn)換參數(shù)的時(shí)候,將輸入?yún)?shù)全部視為 String 類型。雖然我們定義 id 和 code 類型不同,但是在匹配的時(shí)候,都是按照字符串匹配的。如果存在相同值,就會(huì)產(chǎn)生歧義。

Converter 和 ConverterFactory

根據(jù)規(guī)范,接下來(lái)定義一下 Converter 和 ConverterFactory。這些是 Spring 留給我們的擴(kuò)展口,按照規(guī)范定義即可。

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

這兩個(gè)就是轉(zhuǎn)換的核心了,我們只要將他們裝配到 Spring 的類型轉(zhuǎn)換器中,就能夠?qū)崿F(xiàn)枚舉類型的自動(dòng)轉(zhuǎn)化了。

加載配置

將我們定義的 Converter 和 ConverterFactory 注冊(cè)到 Spring 的類型轉(zhuǎn)換器中。

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

至此,核心定義全部結(jié)束。

測(cè)試

寫一個(gè) Controller 作為測(cè)試入口:

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

準(zhǔn)備測(cè)試用例測(cè)試:

@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); }}總結(jié)

實(shí)現(xiàn)枚舉參數(shù)并不難,只要按照 Spring 的擴(kuò)展規(guī)范實(shí)現(xiàn)即可。需要注意的是,注意枚舉類中唯一的 id 和 code。

本文是應(yīng)用,下篇說(shuō)一下原理。以及 http body 形式請(qǐng)求的枚舉轉(zhuǎn)換邏輯。

本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注好吧啦網(wǎng)的更多內(nèi)容!

標(biāo)簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲va中文在线播放免费| 久久精品欧美一区| 在线日韩av| 国产一区日韩一区| 欧美日韩视频| 视频精品一区| 日韩二区在线观看| 欧美日韩国产综合网| 欧美日韩视频| 亚洲91视频| 999精品色在线播放| 日韩久久精品| 极品裸体白嫩激情啪啪国产精品| 日韩三级一区| 在线视频亚洲欧美中文| 欧美日韩国产探花| 亚洲精品乱码久久久久久蜜桃麻豆| 97久久超碰| 成人午夜精品| 免播放器亚洲一区| 久久99久久人婷婷精品综合| xxxxx性欧美特大| 天堂va蜜桃一区二区三区| 国产高清日韩| av不卡在线看| 国产一区福利| 免费观看在线综合色| 国产一区二区三区久久久久久久久| 日韩精品免费一区二区三区| 日韩精品中文字幕一区二区| 久久一区欧美| 精品欧美激情在线观看| 日韩av黄色在线| 亚洲高清二区| 精品99在线| 91精品美女| 三级亚洲高清视频| 日韩毛片在线| 久久精品午夜| 日韩av二区在线播放| 亚洲综合电影一区二区三区| 老牛影视精品| 国产精久久久| 国产午夜精品一区在线观看| 亚洲激情二区| 波多野结衣久久精品| 国产欧美自拍| 亚洲图片久久| 免费精品视频| 国精品一区二区三区| 一区二区三区四区日本视频| 日韩欧美2区| 欧美日韩国产免费观看| 亚洲免费成人av在线| 午夜在线视频一区二区区别| 另类综合日韩欧美亚洲| 国产国产精品| 高清一区二区三区| 国产精区一区二区| 综合激情婷婷| 99精品99| 91精品推荐| 中文在线中文资源| 捆绑调教美女网站视频一区| 欧美午夜精彩| 日本一区二区高清不卡| 日本综合精品一区| 中文精品电影| 亚洲女同中文字幕| 日韩美女一区二区三区在线观看| 午夜亚洲福利| 国产亚洲亚洲| 欧美日韩精品一本二本三本| 天堂av在线| 国产一二在线播放| 国产美女久久| 首页国产欧美久久| 国产午夜精品一区二区三区欧美 | 日韩不卡在线观看日韩不卡视频| 欧美日韩水蜜桃| 亚洲黄色中文字幕| 精品亚洲二区| 久久久国产精品入口麻豆| 国产精品密蕾丝视频下载| 日本欧美大码aⅴ在线播放| 视频在线观看一区二区三区| 西西人体一区二区| 综合精品一区| 亚洲专区视频| 日韩精品一区二区三区免费观影 | 蜜臀久久精品| 91视频一区| 国产精品99久久精品| 麻豆91精品视频| 韩日一区二区| 亚洲无线一线二线三线区别av| 激情久久久久久久| 日韩免费在线| 国产综合亚洲精品一区二| 免费欧美一区| 美女网站一区| 亚洲五月综合| 国产日韩欧美在线播放不卡| 国产麻豆一区二区三区精品视频| 九九99久久精品在免费线bt| 97精品在线| 国产亚洲亚洲| 69堂免费精品视频在线播放| 久久只有精品| 久久久久国产| 日本一区福利在线| 久久av资源| 老司机精品视频在线播放| 激情综合婷婷| 亚洲欧美久久| 老司机精品在线| 国产乱码精品一区二区亚洲| 国产一区精品福利| 午夜一级久久| 成人污污视频| 亚洲三级视频| 水蜜桃精品av一区二区| 老司机久久99久久精品播放免费| 久久亚洲精精品中文字幕| 最新亚洲一区| 成人影视亚洲图片在线| 亚洲毛片在线免费| av在线最新| 亚洲精品日本| 成人台湾亚洲精品一区二区| 日韩视频一区| 日韩成人精品一区| 日韩国产欧美三级| 午夜国产精品视频免费体验区| 国产毛片精品| 91麻豆精品激情在线观看最新| 色8久久久久| 欧美在线亚洲综合一区| 国产福利电影在线播放| 日韩专区视频网站| 99视频在线精品国自产拍免费观看| 高清av一区| 最新国产精品视频| 99成人在线| 欧美特黄一区| 亚洲激情不卡| 欧美精品一二| 久久视频精品| 日韩高清欧美| 日韩精品免费一区二区三区| 久久一区精品| 国产精品久久久久久久免费观看| 国产精品一区二区三区www| 日韩成人av影视| 国产日韩亚洲| 久久精品国产久精国产| 久久精品99久久久| 亚洲欧美日韩一区在线观看| 亚洲爱爱视频| 午夜在线一区二区| 一本一道久久a久久| 三级亚洲高清视频| 69堂免费精品视频在线播放| 91大神在线观看线路一区| 国产伦精品一区二区三区视频| 久久黄色影视| 国产成人精品一区二区免费看京| 日韩精品不卡一区二区| 久久一区二区中文字幕| 国产精品日韩| 奇米狠狠一区二区三区| 国产日韩一区二区三免费高清 | 精品成av人一区二区三区| 高清av一区| 国产视频一区免费看| 日本欧美一区二区| 国产不卡精品| 亚洲一区二区三区四区五区午夜 | 日韩精品成人在线观看| 国产精品天天看天天狠| 五月激情久久| 亚洲神马久久| 国产精品18| 免费观看久久av| 日韩国产在线一| 免费福利视频一区二区三区| 国产亚洲在线| 免费看久久久| 国产亚洲永久域名| 免费看久久久| 老司机久久99久久精品播放免费| 国产精东传媒成人av电影| 亚洲v在线看| 麻豆视频久久| 丝瓜av网站精品一区二区| 国内一区二区三区| 尤物精品在线| 日韩电影免费网址| 精品国产a一区二区三区v免费| 日韩欧美中文在线观看|