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

一文詳解Java項(xiàng)目中如何優(yōu)雅的使用枚舉類型

 更新時(shí)間:2024年03月14日 09:47:17   作者:趙俠客  
枚舉類型在開發(fā)中是很常見的,有非常多的應(yīng)用場(chǎng)景,這篇文章我們就來學(xué)習(xí)一下項(xiàng)目中如何優(yōu)雅的使用枚舉類型,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

枚舉類型在開發(fā)中是很常見的,有非常多的應(yīng)用場(chǎng)景,如狀態(tài)管理、類型分類、權(quán)限控制、配置管理、錯(cuò)誤碼管理、日志級(jí)別等。正確合理的使用枚舉可以給我們帶來非常多的好處:

  • 增強(qiáng)代碼可讀性:枚舉可以使得代碼更加清晰、易于理解。它們提供了一種方式來組織和表示相關(guān)的常量值,使得代碼更易于閱讀和維護(hù)。
  • 類型安全性:枚舉類型能夠限制變量的值,只能取枚舉類型中定義的常量之一,從而避免了錯(cuò)誤的賦值。這有助于減少代碼中的錯(cuò)誤,并提高代碼的穩(wěn)定性。
  • 更好的維護(hù)性:枚舉類型可以在編譯時(shí)進(jìn)行類型檢查,這有助于更早地發(fā)現(xiàn)和修復(fù)問題。此外,由于枚舉類型中的常量值是預(yù)定義的,因此可以減少對(duì)常量值的修改,從而簡(jiǎn)化代碼的維護(hù)。
  • 更好的性能:枚舉類型的值是在編譯時(shí)確定的,因此在運(yùn)行時(shí)訪問枚舉類型的值會(huì)更快。此外,由于枚舉類型中的常量值是唯一的,因此可以直接使用“==”進(jìn)行兩個(gè)值之間的對(duì)比,這有助于提高性能。
  • 更好的組織性:枚舉類型可以幫助我們將相關(guān)的值組織在一起,使代碼更加整潔。通過將相關(guān)的常量值組合在一起,可以使代碼更加易于理解和維護(hù)。
  • 可擴(kuò)展性:枚舉類型可以輕松地?cái)U(kuò)展或更新,而不會(huì)對(duì)其他部分的代碼造成影響。這有助于保持代碼的靈活性和可擴(kuò)展性。
  • 便于測(cè)試:枚舉類型可以方便地進(jìn)行測(cè)試,因?yàn)樗鼈兙哂杏邢耷掖_定的值域。這使得測(cè)試人員可以更容易地覆蓋所有可能的場(chǎng)景,并確保代碼的正確性。

雖然枚舉有諸多的好處,但是使用枚舉也給我們帶來了一些困擾:

  • 前后端數(shù)據(jù)格式轉(zhuǎn)換:前端主要給用戶展示數(shù)據(jù),不能直接顯示枚舉值,需要前端將枚舉轉(zhuǎn)成用戶可讀的數(shù)據(jù)顯示
  • 數(shù)據(jù)庫(kù)的存儲(chǔ):代碼中的枚舉類型無法直接存儲(chǔ)數(shù)據(jù)庫(kù),一般轉(zhuǎn)成數(shù)值類型,這樣還可以減少存儲(chǔ)空間
  • 代碼中大量類型轉(zhuǎn)換:查詢時(shí)需要數(shù)值類型轉(zhuǎn)成枚舉類型,保存時(shí)又需要將枚舉類型轉(zhuǎn)成數(shù)值類型

針對(duì)枚舉存在的問題,本文介紹一種枚舉從數(shù)據(jù)庫(kù)-->后端代碼-->前端代碼-->頁(yè)面和從頁(yè)面-->前端代碼-->后端代碼-->數(shù)據(jù)庫(kù)的自動(dòng)轉(zhuǎn)換方案,大大方便前后端使用枚舉類型。

自動(dòng)轉(zhuǎn)換目標(biāo)

我們以用戶狀態(tài)為例,用戶有兩種狀態(tài):禁用和啟用

前端頁(yè)面:前端頁(yè)面顯示用戶狀態(tài)時(shí)用“禁用、啟用”;

前端代碼:前端代碼里處理用戶狀態(tài)時(shí)用:“ENABLE、DISABLE”或者用“0、1”;

后端代碼:后端代碼使用StatusEnum枚舉類;

數(shù)據(jù)庫(kù):數(shù)據(jù)庫(kù)存儲(chǔ)用戶狀態(tài)時(shí)禁用存1、啟用存0。 

我們的目標(biāo)是讓枚舉在各個(gè)環(huán)境流轉(zhuǎn)時(shí)全自動(dòng)轉(zhuǎn)換。

代碼與數(shù)據(jù)庫(kù)自動(dòng)轉(zhuǎn)換

第一步創(chuàng)建統(tǒng)一的枚舉基類BaseEnum

public interface BaseEnum {
    int getCode();
    String getName();
    String getEnumName();
    static <T extends BaseEnum> T getInstance(Class<T> clazz, String value) {
        T[] constants = clazz.getEnumConstants();
        for (T t : constants) {
            if(StrUtil.isNumeric(value)){
                if (t.getCode() == Integer.parseInt(value)) {
                    return t;
                }
            }else {
                if (t.getEnumName().equals(value)) {
                    return t;
                }
            }
        }
        return null;
    }
}

第二步創(chuàng)建用戶狀態(tài)類StatusEnum實(shí)現(xiàn)BaseEnum接口

public enum StatusEnum implements BaseEnum {
    ENABLE(0,"啟用"),
    DISABLE(1,"禁用");
    @EnumValue
    private int code;
    private String name;
    StatusEnum(int code, String name) {
        this.code = code;
        this.name=name;
    }
    @Override
    public int getCode() {
        return code;
    }
    @Override
    public String getName() {
        return name;
    }
    @Override
    public String getEnumName() {
        return this.name();
    }
}

BaseEnum主要有三個(gè)方法

  • getCode()獲取枚舉的數(shù)值如“0、1”;
  • getName()獲取枚舉顯示值如“禁用、啟用” ;
  • getEnumName()獲取枚舉的枚舉值如“ENABLE、DISABLE”.

如果使用MybatisPlus, 可以使用@EnumValue注解很方便的幫我們解決數(shù)據(jù)庫(kù)與實(shí)體對(duì)象中枚舉類型的相互轉(zhuǎn)換,如果只使用的Mybatis可以自定義TypeHandler來解決數(shù)據(jù)庫(kù)到JAVA枚舉對(duì)象的自動(dòng)轉(zhuǎn)換。

第三步創(chuàng)建用戶類User用戶狀態(tài)使用StatusEnum

@Data
@TableName("user")
public class User {
    private Long id;
    private String userName;
    private StatusEnum status;
}

前后端相互轉(zhuǎn)換

當(dāng)前端查詢用戶時(shí),我們希望將枚舉的三個(gè)屬性都返回給前端,前端頁(yè)面顯示時(shí)取status.name代碼中使用status.enum或者status.code

{
  "id": 3581209395268,
  "userName": "test2@8531.cn",
  "status": {
    "name": "禁用",
    "enum": "DISABLE",
    "code": 1
  }
}

為了達(dá)到將枚舉序列化成一個(gè)json對(duì)象,我們需要自定義序列化器和反序列化器,以下以SpringBoot自帶的Jackson為例:

public class BaseEnumSerializer extends StdSerializer<BaseEnum> {
    public BaseEnumSerializer() {
        this(null);
    }
    public BaseEnumSerializer(Class<BaseEnum> t) {
        super(t);
    }
    @Override
    public void serialize(BaseEnum value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("name",value.getName());
        gen.writeStringField("enum",value.getEnumName());
        gen.writeNumberField("code",value.getCode());
        gen.writeEndObject();;
    }
}
public class BaseEnumDeserializer<T extends BaseEnum> extends StdDeserializer<T> {
    private Class<T> type;
    public BaseEnumDeserializer() {
        this(null);
    }
    public BaseEnumDeserializer(Class<T> vc) {
        super(vc);
        type = vc;
    }
    @Override
    public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        return BaseEnum.getInstance(type, p.getText());
    }
}

自定義Jackson序列化器與反序列化器只能解決數(shù)據(jù)類型為application/json格式的請(qǐng)求,當(dāng)請(qǐng)求類型為application/x-www-form-urlencoded我們還需要自定義Spring消息轉(zhuǎn)換器

public class NumBaseEnumConverterFactory implements ConverterFactory<Number, BaseEnum> {
    @Override
    public <T extends BaseEnum> Converter<Number, T> getConverter(Class<T> aClass) {
        return new NumberToEnumConverter<>(aClass);
    }
    private final class NumberToEnumConverter<T extends BaseEnum> implements Converter<Number, T> {
        private Class<T> enumType;
        public NumberToEnumConverter(Class<T> enumType) {
            this.enumType = enumType;
        }
        @Override
        public T convert(Number s) {
            return BaseEnum.getInstance(enumType,s.toString());
        }
    }
}

public class StrBaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
    @Override
    public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> aClass) {
        return new StringToEnumConverter<>(aClass);
    }
    private final class StringToEnumConverter<T extends BaseEnum> implements Converter<String, T> {
        private Class<T> enumType;
        public StringToEnumConverter(Class<T> enumType) {
            this.enumType = enumType;
        }
        @Override
        public T convert(String s) {
            return BaseEnum.getInstance(enumType,s);
        }
    }
}

以上兩個(gè)消息轉(zhuǎn)換器可以在數(shù)據(jù)格式以表單形式提交時(shí)將數(shù)值類型(0、1)和枚舉值類型(ENABLE、DISABLE)轉(zhuǎn)成枚舉類型。

將自定義好的數(shù)據(jù)轉(zhuǎn)換器注入到Spring中,這樣就完成所有枚舉自動(dòng)轉(zhuǎn)換。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(BaseEnum.class, new BaseEnumSerializer());
        module.addDeserializer(BaseEnum.class, new BaseEnumDeserializer<>());
        mapper.registerModule(module);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return mapper;
    }
     @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(new StrBaseEnumConverterFactory());
        registry.addConverterFactory(new NumBaseEnumConverterFactory());
    }
}

查詢用戶

GET http://localhost:90/user/3581209395268
返回:
{
  "id": 3581209395268,
  "userName": "test2@8531.cn",
  "status": {
    "name": "啟用",
    "enum": "ENABLE",
    "code": 0
  }
}

application/json格式傳參

POST http://localhost:90/user
Content-Type: application/json

{
  "id": 3581209395268,
  "status": "DISABLE"
}

###
POST http://localhost:90/user
Content-Type: application/json

{
  "id": 3581209395268,
  "status": "0"
}

application/x-www-form-urlencoded格式傳參

PUT http://localhost:90/user
Content-Type: application/x-www-form-urlencoded

id=3581209395268&status=ENABLE
###
PUT http://localhost:90/user
Content-Type: application/x-www-form-urlencoded

id=3581209395268&status=1

###
PUT http://localhost:90/user/3581209395268?status=ENABLE
Content-Type: application/x-www-form-urlencoded

###
PUT http://localhost:90/user/3581209395268?status=1
Content-Type: application/x-www-form-urlencoded

@PathVariable格式傳參

PUT http://localhost:90/user/3581209395268/ENABLE
Content-Type: application/x-www-form-urlencoded

###
PUT http://localhost:90/user/3581209395268/1
Content-Type: application/x-www-form-urlencoded

對(duì)應(yīng)JAVA代碼:

@RestController
public class UserController {
    @Resource
    private UserMapper userMapper;

    @GetMapping("/user/{id}")
    public User getById(@PathVariable Long id) {
        return userMapper.selectById(id);
    }
    
    @PostMapping("/user")
    public User upadteById(@RequestBody User user) {
        userMapper.updateById(user);
        return user;
    }

    @PutMapping("/user")
    public User updateUser(User user) {
        userMapper.updateById(user);
        return user;
    }

    @PutMapping("/user/{id}/{status}")
    public User updateStatus(@PathVariable Long id,@PathVariable StatusEnum status) {
        User user=userMapper.selectById(id);
        user.setStatus(status);
        userMapper.updateById(user);
        return user;
    }

    @PutMapping("/user/{id}")
    public User updateUserStatus(@PathVariable Long id,@RequestParam StatusEnum status) {
        User user=userMapper.selectById(id);
        user.setStatus(status);
        userMapper.updateById(user);
        return user;
    }
}

這樣很方便的解決了枚舉在各個(gè)環(huán)節(jié)的自動(dòng)轉(zhuǎn)換問題,其它枚舉只要實(shí)現(xiàn)BaseEnum接口就能實(shí)現(xiàn)全自動(dòng)轉(zhuǎn)換,前后端用起來也方便了不少。

總結(jié)

本文主要介紹了項(xiàng)目中使用枚舉的優(yōu)缺點(diǎn),并針對(duì)缺點(diǎn)給出了解決方案,解決了枚舉在項(xiàng)目中頻繁轉(zhuǎn)換的問題,當(dāng)然解決的還不是非常完美,比如返回給前端的枚舉格式是:{"enum":"DISABLE","code":1} 但是保存時(shí)傳此數(shù)據(jù)結(jié)構(gòu),后端卻無法正確的轉(zhuǎn)成枚舉,我們可以創(chuàng)建StatusEnumDeserializer,將子json對(duì)象轉(zhuǎn)成對(duì)應(yīng)枚舉就好了,但是范型的寫法目前還不知道怎么寫,不可能增加一個(gè)枚舉寫一個(gè)反序列化器,有知道的可以回復(fù)一下,相互學(xué)習(xí)。

public class StatusEnumDeserializer   extends JsonDeserializer<StatusEnum>  {
    @Override
    public StatusEnum  deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node= p.getCodec().readTree(p);
        if(node.isObject()){
            String name= node.get("enum").toString();
            return BaseEnum.getInstance(StatusEnum.class, name);
        }else {
            return BaseEnum.getInstance(StatusEnum.class, node.textValue());
        }
    }
}

以上就是一文詳解Java項(xiàng)目中如何優(yōu)雅的使用枚舉類型的詳細(xì)內(nèi)容,更多關(guān)于Java枚舉類型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JAVA堆排序算法的講解

    JAVA堆排序算法的講解

    這篇文章主要介紹了JAVA堆排序算法的知識(shí)點(diǎn),文中代碼非常詳細(xì),配合上圖片講解,幫助大家更好的參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • Spring Boot全局異常處理解析

    Spring Boot全局異常處理解析

    這篇文章主要為大家詳細(xì)介紹了Spring Boot全局異常處理的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 代碼生成器MyBatisX:自動(dòng)生成代碼方式

    代碼生成器MyBatisX:自動(dòng)生成代碼方式

    MyBatisX是一款提高開發(fā)效率的插件,可以自動(dòng)生成Mapper、XML和Java實(shí)體類代碼,并支持?jǐn)?shù)據(jù)庫(kù)表的重置和JAP提示,安裝步驟簡(jiǎn)單,只需在IDEA的Plugin市場(chǎng)搜索并安裝MyBatisX,然后打開數(shù)據(jù)庫(kù)窗口選擇表進(jìn)行生成即可
    2024-11-11
  • SpringBoot整合JavaMail郵件的兩種方式

    SpringBoot整合JavaMail郵件的兩種方式

    這篇文章主要介紹了SpringBoot整合JavaMail郵件的兩種方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Java使用wait() notify()方法操作共享資源詳解

    Java使用wait() notify()方法操作共享資源詳解

    這篇文章主要為大家詳細(xì)介紹了Java使用wait() notify()方法操作共享資源,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • SpringBoot3基于 Sa-Token 實(shí)現(xiàn) API 接口簽名校驗(yàn)實(shí)戰(zhàn)

    SpringBoot3基于 Sa-Token 實(shí)現(xiàn) API 接口簽名校驗(yàn)實(shí)戰(zhàn)

    本文介紹了基于Spring Boot 3和Sa-Token框架實(shí)現(xiàn)API接口簽名校驗(yàn)的解決方案,通過sa-token-sign模塊提供開箱即用的簽名校驗(yàn)功能,下面就來詳細(xì)的介紹一下,感興趣的可以了解一下
    2025-12-12
  • springboot接口如何多次獲取request中的body內(nèi)容

    springboot接口如何多次獲取request中的body內(nèi)容

    這篇文章主要介紹了springboot接口多次獲取request中的body內(nèi)容的過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot接受前臺(tái)參數(shù)的6種方式以及統(tǒng)一響應(yīng)代碼示例

    SpringBoot接受前臺(tái)參數(shù)的6種方式以及統(tǒng)一響應(yīng)代碼示例

    這篇文章主要給大家介紹了關(guān)于SpringBoot接受前臺(tái)參數(shù)的6種方式以及統(tǒng)一響應(yīng)的相關(guān)資料,前端負(fù)責(zé)展示頁(yè)面和用戶交互,而后端則負(fù)責(zé)處理業(yè)務(wù)邏輯和數(shù)據(jù)存儲(chǔ),在這種架構(gòu)下前端需要將用戶輸入的數(shù)據(jù)發(fā)送給后端進(jìn)行處理,需要的朋友可以參考下
    2023-12-12
  • 深入理解Swift中的Substring和String

    深入理解Swift中的Substring和String

    這篇文章主要給大家深入的介紹了Swift中Substring和String的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • Java從服務(wù)端下載Excel模板文件的兩種方法

    Java從服務(wù)端下載Excel模板文件的兩種方法

    這篇文章主要為大家詳細(xì)介紹了Java從服務(wù)端下載Excel模板文件的兩種方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評(píng)論

迁西县| 登封市| 台南县| 定陶县| 宣武区| 得荣县| 巢湖市| 水富县| 甘德县| 长泰县| 马尔康县| 峨眉山市| 鹿邑县| 泸水县| 习水县| 乌恰县| 山阴县| 梁平县| 德兴市| 长岛县| 东至县| 开化县| 仙居县| 平武县| 青岛市| 聂荣县| 东源县| 汝南县| 罗定市| 马边| 建宁县| 闵行区| 河曲县| 迭部县| 乌鲁木齐县| 都匀市| 邳州市| 屏山县| 车致| 揭东县| 崇仁县|