服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - SpringBoot 枚举类型的自动转换的实现

SpringBoot 枚举类型的自动转换的实现

2022-10-20 15:08rookie_only Java教程

一般我们在数据库都会定义数值型的枚举常量,不管是序列化还是反序列化都是需要我们手动去转换成枚举类型的,本文主要介绍了Spring Boot 枚举类型的自动转换,感兴趣的可以了解一下

需求:一般我们在数据库都会定义数值型的枚举常量,不管是序列化还是反序列化都是需要我们手动去转换成枚举类型的,既然这样我们能不能让它们自动转换呢?接下来我们就来尝试一下:

首先解决如何接收枚举类型。

枚举父类

?
1
2
3
4
5
6
7
8
9
10
11
/**
 * @author rookie
 */
public interface IEnum<T extends Serializable> {
 
    /**
     * 获取值
     * @return 值
     */
    T getValue();
}

1、请求头接收参数

添加Convert

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Component
public class EnumConvertFactory implements ConverterFactory<String, IEnum<?>> {
 
    @Override
    public <T extends IEnum<?>> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnum<>(targetType);
    }
 
 
    public static class StringToEnum<T extends IEnum<?>> implements Converter<String, T> {
 
        private final Class<T> targetType;
 
        public StringToEnum(Class<T> targetType) {
            this.targetType = targetType;
        }
 
        @Override
        public T convert(String source) {
            if (!StringUtils.hasText(source)) {
                return null;
            }
            return (T) EnumConvertFactory.getEnum(this.targetType, source);
        }
    }
 
    public static <T extends IEnum<?>> T getEnum(Class<T> targetType, String source) {
        for (T constant : targetType.getEnumConstants()) {
            if (source.equals(String.valueOf(constant.getValue()))) {
                return constant;
            }
        }
        return null;
    }
}

注册Convert

?
1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class WebConfig implements WebMvcConfigurer {
 
    @Autowired
    private EnumConvertFactory enumConvertFactory;
 
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(enumConvertFactory);
    }
}

我们只要实现 IEnum ,然后在我们的接收实体类中定义相应的枚举类型就能自动转换成枚举类型了,比如这样:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Getter
@AllArgsConstructor
public enum TestEnum implements IEnum<String>{
 
    /**
     * 测试
     */
    TEST_ENUM("1","2");
    
    private final String value;
 
    private final String msg;
 
}

2、请求体接收

Jackson接收枚举

如果我们接收的是 JSON 字符串类型,那么 Jackson 默认是根据下标进行转换的,和我们根据匹配值获取相应枚举不符,所以进行以下更改:

添加枚举反序列化处理器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Data
@EqualsAndHashCode(callSuper = true)
public class EnumDeserializer extends JsonDeserializer<Enum<?>> implements ContextualDeserializer {
 
    private Class<?> target;
 
    @SuppressWarnings("all")
    @Override
    public Enum<?> deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
        if (!StringUtils.hasText(jsonParser.getText())) {
            return null;
        }
        if (IEnum.class.isAssignableFrom(target)) {
            return (Enum<?>) EnumConvertFactory.getEnum((Class) target, jsonParser.getText());
        }
        return null;
    }
 
    /**
     * @param ctx      ctx
     * @param property property
     * @return 1
     * @throws JsonMappingException
     */
    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctx, BeanProperty property) throws JsonMappingException {
        Class<?> rawCls = ctx.getContextualType().getRawClass();
        EnumDeserializer enumDeserializer = new EnumDeserializer();
        enumDeserializer.setTarget(rawCls);
        return enumDeserializer;
    }
 
}

注册处理器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class JacksonConfig implements SmartInitializingSingleton {
 
    @Autowired
    private ObjectMapper objectMapper;
 
    @Override
    public void afterSingletonsInstantiated() {
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Enum.class, new EnumDeserializer());
        objectMapper.registerModule(simpleModule);
    }  
}

使用方法和上面一致。

3、添加自定义枚举序列化

接下来我们就要解决如何将数据库中的数值常量枚举转换成

jackson 序列化默认是按照名称序列化的,和我们想返回枚举中的某个值不符,下面我们进行一下小的改动:

添加序列化处理器

?
1
2
3
4
5
6
public class IEnumSerializer extends JsonSerializer<IEnum> {
    @Override
    public void serialize(IEnum iEnum, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(iEnum.getName());
    }
}

注册序列化处理器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class BeanLoadProcess implements SmartInitializingSingleton {
 
    @Autowired
    private ObjectMapper objectMapper;
 
    @Override
    public void afterSingletonsInstantiated() {
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(IEnum.class,new IEnumSerializer());
        objectMapper.registerModule(simpleModule);
    }
}

因为我们先一步是让数据库中的常量能转换成枚举类型,这里我们定义一下 Mybatis plus(我用的是plus) 的枚举处理器

?
1
2
3
mybatis-plus:
  configuration:
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler

好了这样就行了。

到此这篇关于Spring Boot 枚举类型的自动转换的文章就介绍到这了,更多相关Spring Boot 枚举类型的自动转换内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7077887412243791903

延伸 · 阅读

精彩推荐