最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2021年08月12日 11:47:26   作者:看山  
這篇文章主要介紹了springboot枚舉類型傳遞的步驟,幫助大家更好的理解和學(xué)習(xí)使用springboot,感興趣的朋友可以了解下,希望能給你帶來幫助

 枚舉參數(shù)

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

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

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

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

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

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

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

確認(rèn)需求

首先確認(rèn)需求。我們期望定義一個(gè)枚舉類作為參數(shù),接口訪問的時(shí)候,可以是 int 類型的 id,id 取值不限于枚舉的序號(hào);也可以是 String 類型的 code,code 取值不限于枚舉的 name。換句話說,這個(gè)枚舉有個(gè) id 和 code,隨意定義,只要接口傳過來匹配上,就能夠自動(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 {
}

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

定義枚舉

前面定義了三個(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ī)范,接下來定義一下 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 unchecked
        Converter<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)換器中。

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

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

測試

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

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

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

@SpringBootTest(classes = SpringEnumParamApplication.class)
@AutoConfigureMockMvc
class 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)用,下篇說一下原理。以及 http body 形式請(qǐng)求的枚舉轉(zhuǎn)換邏輯。

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Java多態(tài)的全面系統(tǒng)解析

    Java多態(tài)的全面系統(tǒng)解析

    多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量到底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定
    2022-03-03
  • Java中Mybatis,SpringMVC,Spring的介紹及聯(lián)系

    Java中Mybatis,SpringMVC,Spring的介紹及聯(lián)系

    這篇文章主要為大家詳細(xì)介紹了Java中Mybatis,SpringMVC,Spring的介紹及聯(lián)系,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • mybatis之嵌套查詢和嵌套結(jié)果有哪些區(qū)別

    mybatis之嵌套查詢和嵌套結(jié)果有哪些區(qū)別

    這篇文章主要介紹了mybatis之嵌套查詢和嵌套結(jié)果有哪些區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • idea環(huán)境下Maven無法正常下載pom中配置的包問題

    idea環(huán)境下Maven無法正常下載pom中配置的包問題

    這篇文章主要介紹了idea環(huán)境下Maven無法正常下載pom中配置的包的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 關(guān)于SpringBoot中的請(qǐng)求映射及使用

    關(guān)于SpringBoot中的請(qǐng)求映射及使用

    這篇文章主要介紹了關(guān)于SpringBoot中的請(qǐng)求映射及使用,Spring Boot 中的授權(quán)機(jī)制,包括基于角色的授權(quán)和基于資源的授權(quán),同時(shí),我們也將給出相應(yīng)的代碼示例,幫助讀者更好地理解和應(yīng)用這些授權(quán)機(jī)制,需要的朋友可以參考下
    2023-07-07
  • Springboot3.3 整合Cassandra 4.1.5的詳細(xì)過程

    Springboot3.3 整合Cassandra 4.1.5的詳細(xì)過程

    這篇文章主要介紹了Springboot3.3 整合Cassandra 4.1.5的詳細(xì)過程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Java 如何使用@Autowired注解自動(dòng)注入bean

    Java 如何使用@Autowired注解自動(dòng)注入bean

    這篇文章主要介紹了Java 使用@Autowired注解自動(dòng)注入bean的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Springboot主程序類注解配置過程圖解

    Springboot主程序類注解配置過程圖解

    這篇文章主要介紹了Springboot主程序類注解配置過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • jstack+jdb命令查看線程及死鎖堆棧信息的實(shí)例

    jstack+jdb命令查看線程及死鎖堆棧信息的實(shí)例

    這篇文章主要介紹了jstack+jdb命令查看線程及死鎖堆棧信息的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 詳解Spring boot操作文件的多種方式

    詳解Spring boot操作文件的多種方式

    這篇文章主要介紹了Spring boot操作文件的幾種方式,主要給大家介紹操作文件的三種方式,每種方式通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-11-11

最新評(píng)論

南木林县| 澳门| 曲松县| 荃湾区| 航空| 内黄县| 左权县| 雷山县| 祥云县| 新晃| 济南市| 通辽市| 扎囊县| 固始县| 南木林县| 年辖:市辖区| 睢宁县| 牟定县| 北京市| 大田县| 湘阴县| 县级市| 城固县| 拉孜县| 卓尼县| 凤城市| 金坛市| 郑州市| 济南市| 商水县| 屏南县| 峡江县| 泸溪县| 新安县| 黑河市| 观塘区| 施秉县| 辰溪县| 启东市| 于田县| 年辖:市辖区|