Spring Boot 2.7.18(最终 2.x 系列版本)3 - 枚举规范定义:定义基础枚举接口;定义枚举工具类;示例枚举

Spring Boot 2.7.18(最终 2.x 系列版本)3 - 枚举规范定义:定义基础枚举接口;定义枚举工具类;示例枚举

Spring Boot 2.7.18(最终 2.x 系列版本)3 - 枚举规范定义


定义基础枚举接口

java 复制代码
package cn.hao.kai.enums;

import java.io.Serializable;

/**
 * <h2>基础枚举接口</h2>
 *
 * <p><strong>说明:</strong></p>
 * <ul>
 *     <li>用于统一枚举结构:值 + 描述,参考 {@link ExampleEnum} 实现</li>
 *     <li>配合 {@link EnumUtil} 使用</li>
 * </ul>
 *
 * @param <V> 枚举编码类型
 * @author Hao Kai
 */
@SuppressWarnings("unused")
public interface IBaseEnum<V> extends Serializable {

    /**
     * 获取枚举编码(唯一标识)
     *
     * @return 枚举编码
     */
    V getEnumCode();

    /**
     * 获取枚举描述
     *
     * @return 枚举描述信息
     */
    String getEnumDescription();
}

定义枚举工具类

java 复制代码
package cn.hao.kai.enums;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;

/**
 * <h2>枚举工具类</h2>
 * 仅适用于实现 {@link IBaseEnum} 接口的枚举类,用于统一处理实现 {@link IBaseEnum} 接口的枚举类,如:值获取、条件查询、转 Map/List、下拉框结构等。
 *
 * <p><strong>主要功能:</strong></p>
 * <ul>
 *     <li>根据 value、name、description 获取枚举实例</li>
 *     <li>自定义条件获取</li>
 *     <li>枚举值存在性校验</li>
 *     <li>转为 Map/List/下拉列表</li>
 *     <li>缓存提升性能</li>
 * </ul>
 *
 * <p><strong>调用示例:</strong>参考 {@link ExampleEnum} 实现</p>
 * <pre>{@code
 * getEnumByEnumCode(ExampleEnum.class, 0);// SUCCESS
 * getEnumByEnumName(ExampleEnum.class, "FAIL"); // FAIL
 * getEnumByEnumDescription(ExampleEnum.class, "成功"); // SUCCESS
 * existsEnumCode(ExampleEnum.class, 1); // true
 * existsEnumName(ExampleEnum.class, "SUCCESS"); // true
 * existsEnumDescription(ExampleEnum.class, "失败"); // true
 * getByCondition(ExampleEnum.class, e -> e.getEnumCode() == 1); // FAIL
 * toList(ExampleEnum.class, "code", "desc"); // [{code=0, desc=成功}, {code=1, desc=失败}]
 * toDropdownList(ExampleEnum.class, "value", "label"); // [{value=0, label=成功}, {value=1, label=失败}]
 * }</pre>
 * 
 * @author Hao Kai
 */
@SuppressWarnings("unused")
public final class EnumUtil {

    /**
     * 枚举值缓存
     */
    private static final Map<Class<?>, Map<Object, Enum<?>>> ENUM_CODE_CACHE = new ConcurrentHashMap<>();
    /**
     * 枚举描述缓存
     */
    private static final Map<Class<?>, Map<String, Enum<?>>> ENUM_DESC_CACHE = new ConcurrentHashMap<>();

    private EnumUtil() {
        throw new UnsupportedOperationException("EnumUtil is a utility class and cannot be instantiated.");
    }

    /**
     * 根据枚举编码获取枚举实例
     *
     * @param enumClass 枚举类
     * @param enumCode  枚举编码
     * @param <E>       枚举类型
     * @param <V>       枚举编码类型
     * @return 匹配的枚举项或 null
     *
     * <pre>{@code
     * EnumUtil.getEnumByEnumCode(Status.class, 0); // => SUCCESS
     * }</pre>
     */
    @SuppressWarnings("unchecked")
    public static <E extends Enum<E> & IBaseEnum<V>, V> E getEnumByEnumCode(Class<E> enumClass, V enumCode) {
        if (enumClass == null || enumCode == null) return null;
        return (E) ENUM_CODE_CACHE
                .computeIfAbsent(enumClass, EnumUtil::initValueCache)
                .get(enumCode);
    }

    /**
     * 根据枚举名获取实例
     *
     * @param enumClass 枚举类
     * @param enumName  枚举名称
     * @param <E>       枚举类型
     * @return 匹配的枚举项或 null
     *
     * <pre>{@code
     * EnumUtil.getEnumByEnumName(Status.class, "SUCCESS"); // => SUCCESS
     * }</pre>
     */
    public static <E extends Enum<E>> E getEnumByEnumName(Class<E> enumClass, String enumName) {
        if (enumClass == null || enumName == null) return null;
        try {
            return Enum.valueOf(enumClass, enumName);
        } catch (IllegalArgumentException e) {
            return null;
        }
    }

    /**
     * 根据枚举描述获取实例
     *
     * @param enumClass       枚举类
     * @param enumDescription 描述
     * @param <E>             枚举类型
     * @return 匹配的枚举项或 null
     *
     * <pre>{@code
     * EnumUtil.getEnumByEnumDescription(Status.class, "失败"); // => FAIL
     * }</pre>
     */
    @SuppressWarnings("unchecked")
    public static <E extends Enum<E> & IBaseEnum<?>> E getEnumByEnumDescription(Class<E> enumClass, String enumDescription) {
        if (enumClass == null || enumDescription == null) return null;
        return (E) ENUM_DESC_CACHE
                .computeIfAbsent(enumClass, EnumUtil::initDescriptionCache)
                .get(enumDescription);
    }

    /**
     * 根据条件获取枚举实例
     *
     * @param enumClass 枚举类
     * @param predicate 条件谓词
     * @param <E>       枚举类型
     * @return 匹配的枚举项或 null
     *
     * <pre>{@code
     * EnumUtil.getByCondition(Status.class, e -> e.getEnumCode() == 1); // => FAIL
     * }</pre>
     */
    public static <E extends Enum<E> & IBaseEnum<?>> E getByCondition(Class<E> enumClass, Predicate<E> predicate) {
        for (E e : enumClass.getEnumConstants()) {
            if (predicate.test(e)) return e;
        }
        return null;
    }

    /**
     * 判断值是否存在
     *
     * @param enumClass 枚举类
     * @param enumCode  枚举编码
     * @param <E>       枚举类型
     * @param <V>       枚举编码类型
     * @return true 表示存在
     *
     * <pre>{@code
     * EnumUtil.existsEnumCode(Status.class, 1); // => true
     * }</pre>
     */
    public static <E extends Enum<E> & IBaseEnum<V>, V> boolean existsEnumCode(Class<E> enumClass, V enumCode) {
        return getEnumByEnumCode(enumClass, enumCode) != null;
    }

    /**
     * 判断名称是否存在
     *
     * @param enumClass 枚举类
     * @param enumName  枚举名称
     * @param <E>       枚举类型
     * @return true 表示存在
     */
    public static <E extends Enum<E>> boolean existsEnumName(Class<E> enumClass, String enumName) {
        return getEnumByEnumName(enumClass, enumName) != null;
    }

    /**
     * 判断描述是否存在
     *
     * @param enumClass       枚举类
     * @param enumDescription 枚举描述
     * @param <E>             枚举类型
     * @return true 表示存在
     */
    public static <E extends Enum<E> & IBaseEnum<?>> boolean existsEnumDescription(Class<E> enumClass, String enumDescription) {
        return getEnumByEnumDescription(enumClass, enumDescription) != null;
    }

    /**
     * 枚举转为 Map 列表
     *
     * @param enumClass      枚举类
     * @param codeKey        map 中的 code 字段名
     * @param descriptionKey map 中的 description 字段名
     * @param <E>            枚举类型
     * @return list of map
     *
     * <pre>{@code
     * EnumUtil.toList(Status.class, "code", "desc"); // [{code=0, desc=成功}, {code=1, desc=失败}]
     * }</pre>
     */
    public static <E extends Enum<E> & IBaseEnum<?>> List<Map<String, Object>> toList(
            Class<E> enumClass,
            String codeKey,
            String descriptionKey
    ) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (E e : enumClass.getEnumConstants()) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put(codeKey, e.getEnumCode());
            map.put(descriptionKey, e.getEnumDescription());
            list.add(map);
        }
        return list;
    }

    /**
     * 枚举转为下拉列表结构
     *
     * @param enumClass 枚举类
     * @param valueKey  下拉框 value 字段名
     * @param labelKey  下拉框 label 字段名
     * @param <E>       枚举类型
     * @return 下拉框数据
     *
     * <pre>{@code
     * EnumUtil.toDropdownList(Status.class, "value", "label"); // [{value=0, label=成功}, {value=1, label=失败}]
     * }</pre>
     */
    public static <E extends Enum<E> & IBaseEnum<?>> List<Map<String, Object>> toDropdownList(
            Class<E> enumClass,
            String valueKey,
            String labelKey
    ) {
        return toList(enumClass, valueKey, labelKey);
    }

    // ===== 缓存初始化 =====
    @SuppressWarnings("unchecked")
    private static Map<Object, Enum<?>> initValueCache(Class<?> enumClass) {
        Map<Object, Enum<?>> map = new HashMap<>();
        for (Enum<?> e : ((Class<? extends Enum<?>>) enumClass).getEnumConstants()) {
            IBaseEnum<?> base = (IBaseEnum<?>) e;
            map.put(base.getEnumCode(), e);
        }
        return map;
    }

    @SuppressWarnings("unchecked")
    private static Map<String, Enum<?>> initDescriptionCache(Class<?> enumClass) {
        Map<String, Enum<?>> map = new HashMap<>();
        for (Enum<?> e : ((Class<? extends Enum<?>>) enumClass).getEnumConstants()) {
            IBaseEnum<?> base = (IBaseEnum<?>) e;
            map.put(base.getEnumDescription(), e);
        }
        return map;
    }

    /**
     * <h3>演示主方法</h3>
     * 用于测试全部方法是否工作正常
     */
    public static void main(String[] args) {
        System.out.println("== getEnumByEnumCode: " + getEnumByEnumCode(ExampleEnum.class, 0));// SUCCESS
        System.out.println("== getEnumByEnumName: " + getEnumByEnumName(ExampleEnum.class, "FAIL")); // FAIL
        System.out.println("== getEnumByEnumDescription: " + getEnumByEnumDescription(ExampleEnum.class, "成功")); // SUCCESS
        System.out.println("== existsEnumCode: " + existsEnumCode(ExampleEnum.class, 1)); // true
        System.out.println("== existsEnumName: " + existsEnumName(ExampleEnum.class, "SUCCESS")); // true
        System.out.println("== existsEnumDescription: " + existsEnumDescription(ExampleEnum.class, "失败")); // true
        System.out.println("== getByCondition: " + getByCondition(ExampleEnum.class, e -> e.getEnumCode() == 1)); // FAIL
        System.out.println("== toList: " + toList(ExampleEnum.class, "code", "desc")); // [{code=0, desc=成功}, {code=1, desc=失败}]
        System.out.println("== toDropdownList: " + toDropdownList(ExampleEnum.class, "value", "label")); // [{value=0, label=成功}, {value=1, label=失败}]
    }

}

示例枚举

java 复制代码
package cn.hao.kai.enums;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 示例枚举 ExampleEnum
 * <p>
 * 使用说明:
 * <ul>
 *   <li>前端需要同时获取枚举的 code 和 desc 字段。</li>
 *   <li>使用 {@link com.fasterxml.jackson.annotation.JsonFormat#shape()} = {@link com.fasterxml.jackson.annotation.JsonFormat.Shape#OBJECT}
 *       使枚举以对象形式序列化,例如:
 *       <pre>
 *       {
 *         "code": 0,
 *         "desc": "成功"
 *       }
 *       </pre>
 *   </li>
 *   <li>由于实现了接口 {@code IBaseEnum},Jackson 会默认将 {@code getEnumCode()}、
 *       {@code getEnumDescription()} 一并序列化为属性。</li>
 *   <li>为避免重复字段,使用 {@link com.fasterxml.jackson.annotation.JsonIgnore}
 *       忽略这些方法的序列化。</li>
 * </ul>
 * </p>
 *
 * @author Hao Kai
 */
@Getter
@AllArgsConstructor
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ExampleEnum implements IBaseEnum<Integer> {
    SUCCESS(0, "成功"),
    FAIL(1, "失败");

    private final Integer code;
    private final String desc;

    @JsonIgnore
    @Override
    public Integer getEnumCode() {
        return code;
    }

    @JsonIgnore
    @Override
    public String getEnumDescription() {
        return desc;
    }
}
相关推荐
Swizard2 小时前
别再让你的 Python 傻等了:三分钟带你通过 asyncio 实现性能起飞
python
凯歌的博客2 小时前
springboot项目jar包启动, 配置文件外置
chrome·spring boot
鼠爷ねずみ2 小时前
SpringCloud前后端整体开发流程-以及技术总结文章实时更新中
java·数据库·后端·spring·spring cloud
oden3 小时前
0成本搭建!20分钟用 Workers AI + Vectorize 搞定 RAG(附全套源码)
后端
Darkershadow4 小时前
python学习之串口通信
python·学习
3824278274 小时前
python:输出JSON
前端·python·json
不会画画的画师4 小时前
Go开发指南:io/ioutil包应用和迁移指南
开发语言·后端·golang
JIngJaneIL5 小时前
基于java + vue个人博客系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
也许是_5 小时前
大模型应用技术之 详解 MCP 原理
人工智能·python