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;
    }
}
相关推荐
q***7482 小时前
Spring Boot 3.x 系列【3】Spring Initializr快速创建Spring Boot项目
spring boot·后端·spring
q***18062 小时前
十八,Spring Boot 整合 MyBatis-Plus 的详细配置
spring boot·后端·mybatis
钅日 勿 XiName2 小时前
一小时速通Pytorch之自动梯度(Autograd)和计算图(Computational Graph)(二)
人工智能·pytorch·python
m0_736927042 小时前
2025高频Java后端场景题汇总(全年汇总版)
java·开发语言·经验分享·后端·面试·职场和发展·跳槽
掘金者阿豪2 小时前
“多余的”回车:从IDE的自动换行窥见软件工程的规范与协作
后端
故林丶2 小时前
【Django】Django笔记
python·django
Felix_XXXXL3 小时前
Plugin ‘mysql_native_password‘ is not loaded`
java·后端
IT北辰3 小时前
Python实现居民供暖中暖气能耗数据可视化分析(文中含源码)
开发语言·python·信息可视化
FreeCode3 小时前
LangChain1.0智能体开发:长期记忆
python·langchain·agent