java 枚举 Enum 和 数据库 和 前端 对应问题

63 阅读2分钟

参考文章:

blog.csdn.net/2301_804686…

zhuanlan.zhihu.com/p/150370826…

下面是枚举类:

private HotsoptStatusEnum markerStatus;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Getter;

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
@Getter
@AllArgsConstructor
public enum HotsoptStatusEnum {

    NORMAL("0", "正常"),
    OFF_SHELF("1", "下架"),
   
    @EnumValue
    private final String code;
    private final String msg;

}

存在的问题: 给前端传 0 和 正常 用于显示 ,但是查询的时候前端 必须给后端传 NORMAL 才能查询到

之前的解决办法是:

NORMAL("0","NORMAL", "正常"), 把 NORMAL 给前端返回,查询的时候,让前端传 NORMAL

使用下面的解决方案能实现:

1、存到数据库是 0

2、返给前端是 0 和 正常,便于前端 select 显示

3、查询的时候,给 0 或 NORMAL ,都能查询

特别注意的是:

枚举类 @EnumValue 必须加上这个注解,程序才能执行到 下面的 StringToEnumConverterFactory

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.baomidou.mybatisplus.annotation.IEnum;
import lombok.extern.slf4j.Slf4j;
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.lang.NonNull;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;

@Slf4j
public class StringToEnumConverterFactory implements ConverterFactory<String, Enum<?>> {

    private static final Map<Class<?>, Converter<String, ? extends Enum<?>>> CONVERTER_MAP = new ConcurrentHashMap<>();
    private static final Map<Class<?>, Method> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();

    public static <T> Method getMethod(Class<T> enumType) {
        Method method;
        // 找到取值的方法
        if (IEnum.class.isAssignableFrom(enumType)) {
            try {
                method = enumType.getMethod("getValue");
            } catch (NoSuchMethodException e) {
                throw new IllegalArgumentException(String.format("类:%s 找不到 getValue方法",
                        enumType.getName()));
            }
        } else {
            method = TABLE_METHOD_OF_ENUM_TYPES.computeIfAbsent(enumType, k -> {
                Field field =
                        dealEnumType(enumType).orElseThrow(() -> new IllegalArgumentException(String.format(
                                "类:%s 找不到 EnumValue注解", enumType.getName())));
                return ReflectionKit.getMethod(enumType, field);
            });
        }
        return method;
    }

    private static Optional<Field> dealEnumType(Class<?> clazz) {
        return clazz.isEnum() ?
                Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst() : Optional.empty();
    }

    @NonNull
    @Override
    @SuppressWarnings("unchecked cast")
    public <T extends Enum<?>> Converter<String, T> getConverter(@NonNull Class<T> targetType) {
        // 缓存转换器
        Converter<String, T> converter = (Converter<String, T>) CONVERTER_MAP.get(targetType);
        if (converter == null) {
            converter = new StringToEnumConverter<>(targetType);
            CONVERTER_MAP.put(targetType, converter);
        }
        return converter;
    }

    static class StringToEnumConverter<T extends Enum<?>> implements Converter<String, T> {

        private final Map<String, T> enumMap = new ConcurrentHashMap<>();

        StringToEnumConverter(Class<T> enumType) {
            Method method = getMethod(enumType);
            T[] enums = enumType.getEnumConstants();

            // 将值与枚举对象对应并缓存
            for (T e : enums) {
                try {
                    enumMap.put(method.invoke(e).toString(), e);
                } catch (Exception ex) {
                    log.error("获取枚举值错误!!! ", ex);
                }
            }
        }


        @Override
        public T convert(@NonNull String source) {
            // 获取
            T t = enumMap.get(source);
            if (t == null) {
                throw new IllegalArgumentException("该字符串找不到对应的枚举对象 字符串:" + source);
            }
            return t;
        }
    }
}

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionKit {

    /**
     * 根据枚举类型和字段获取对应的 getter 方法
     * @param enumType 枚举类型
     * @param field 字段
     * @return getter 方法
     * @throws NoSuchMethodException 如果找不到对应的方法
     */
    public static Method getMethod(Class<?> enumType, Field field){
        String fieldName = field.getName();
        String methodName;
        if (boolean.class.equals(field.getType()) || Boolean.class.equals(field.getType())) {
            // 布尔类型字段使用 isXxx()
            methodName = "is" + capitalize(fieldName);
        } else {
            // 其他类型字段使用 getXxx()
            methodName = "get" + capitalize(fieldName);
        }
        try {
            return enumType.getMethod(methodName);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将字符串的首字母大写
     * @param str 输入字符串
     * @return 首字母大写后的字符串
     */
    private static String capitalize(String str) {
        if (str == null || str.length() == 0) {
            return str;
        }
        return Character.toUpperCase(str.charAt(0)) + str.substring(1);
    }
}
@Slf4j
@Configuration
public class GlobWebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(new StringToEnumConverterFactory());
    }
}