参考文章:
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());
}
}