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

 更新时间:2022年03月24日 10:36:49   作者:rookie_only  
一般我们在数据库都会定义数值型的枚举常量,不管是序列化还是反序列化都是需要我们手动去转换成枚举类型的,本文主要介绍了Spring Boot 枚举类型的自动转换,感兴趣的可以了解一下

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

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

枚举父类

/**
 * @author rookie
 */
public interface IEnum<T extends Serializable> {

    /**
     * 获取值
     * @return 值
     */
    T getValue();
}

1、请求头接收参数

添加Convert

@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

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private EnumConvertFactory enumConvertFactory;

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(enumConvertFactory);
    }
}

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

@Getter
@AllArgsConstructor
public enum TestEnum implements IEnum<String>{

    /**
     * 测试
     */
    TEST_ENUM("1","2");
    
    private final String value;

    private final String msg;

}

2、请求体接收

Jackson接收枚举

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

添加枚举反序列化处理器

@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;
    }

}

注册处理器

@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 序列化默认是按照名称序列化的,和我们想返回枚举中的某个值不符,下面我们进行一下小的改动:

添加序列化处理器

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

注册序列化处理器

@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) 的枚举处理器

mybatis-plus:
  configuration:
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler

好了这样就行了。

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

相关文章

  • java+selenium爬取图片签名的方法

    java+selenium爬取图片签名的方法

    这篇文章主要为大家详细介绍了java+selenium爬取图片签名的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • SpringBoot集成cache缓存的实现

    SpringBoot集成cache缓存的实现

    日常开发中,缓存是解决数据库压力的一种方案,本文记录springboot中使用cache缓存。需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • java中staticclass静态类详解

    java中staticclass静态类详解

    这篇文章主要介绍了java中staticclass静态类详解,具有一定借鉴价值,需要的朋友可以了解下。
    2017-12-12
  • java实现文件上传、下载、图片预览

    java实现文件上传、下载、图片预览

    这篇文章主要介绍了java实现文件上传、下载、图片预览,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • SpringBoot下载文件遇到文件损坏等问题解决方案

    SpringBoot下载文件遇到文件损坏等问题解决方案

    调用接口下载spring boot工程的resources目录下的excel模板文件,非常常见的一个文件下载功能,但是却容易遇到很多坑,下面总结记录下
    2023-10-10
  • Java中Stringbuild,Date和Calendar类的用法详解

    Java中Stringbuild,Date和Calendar类的用法详解

    这篇文章主要为大家详细介绍了Java中Stringbuild、Date和Calendar类的用法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-04-04
  • SpringBoot结合WebSocket实现聊天功能

    SpringBoot结合WebSocket实现聊天功能

    本文介绍了如何使用SpringBoot和WebSocket实现一个简单的聊天功能,包括导入依赖、配置类、创建消息实体、指定ServerEndpoint、创建客户端等步骤,通过具体示例,演示了如何发送个人消息和群发消息,实现了基本的聊天功能,适合需要在项目中实现实时通讯功能的开发者参考
    2024-11-11
  • 浅谈Springboot实现拦截器的两种方式

    浅谈Springboot实现拦截器的两种方式

    本文详细的介绍了Springboot拦截器的两种方式实现,一种就是用拦截器,一种就是过滤器,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • java并发无锁多线程单线程示例详解

    java并发无锁多线程单线程示例详解

    这篇文章主要为大家介绍了java并发无锁多线程单线程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • SpringBoot通过ip获取归属地的几种方式分享

    SpringBoot通过ip获取归属地的几种方式分享

    在日常我们逛网站的时候会发现我们登录后会出现归属地信息,例如:我在广州登录会显示广东广州,有些更加精确的会显示到区县,那么我们来看看有哪些方式来获取归属地信息,今天我们来聊一聊
    2023-09-09

最新评论