枚举转换踩坑

记录下在服务调用之下,存在几种枚举转换的情况,如有问题,请多指正。

流程分析

  1. 前端发起请求时,例如传入sex(性别)为1(男)的参数,在接收到请求时,后端采用SexType sex枚举类型进行接收,那么此时会发生一次枚举转换即枚举的反序列化,将1转为SexType.MAN

    • 如果请求方式是Get、DELETE,会调用Spring提供的函数进行转换
    • 如果请求方式是POST、PUT,会调用默认的json解析框架(JackSon)进行转换
  2. 后端会调用服务(OpenFeign)接口,在MyFeignConfig中配置请求拦截会将第一步中的请求头参数传递到服务接收方的请求头中,然后执行第一步中的转换。

  3. 使用对象拷贝hutool的BeanUtil.copyProperties函数将VO类转为实体类,进行数据库的查询,在对象拷贝过程中可能会发生枚举类转整形的情况,这时会调用hutool提供的转换器

  4. 在执行数据库查询时,传入QueryWrapper中,指定sexSexType.MAN。生成sql时会调用mybatis-plus的类型转换器,将枚举转为具体的值(MybatisEnumTypeHandler

    setParameter:57, CompositeEnumTypeHandler

  5. 数据库查询后,再次调用MybatisEnumTypeHandler转换器将原始值转为枚举

  6. 所有步骤执行完成需要将数据返给服务调用方

    1. 如果被JEECG字典切面拦截,那么会先调用jackson提供的objectMapper.writeValueAsString将对象转为json格式的字符串,此时枚举值变成了原始值,再后续字典翻译的流程,流程结束后返回的对象为JSONObject类型,再执行下面序列化的流程.

    2. 对于增加了@ResponseBody注解的方法,会调用默认JSON工具objectWriter.writeValue(generator, value),对最终的响应进行JSON序列化。

  7. open-feign接收到请求响应后,会将响应结果转化为指定返回值类型,此时会使用fastjson库进行枚举的反序列化。

  8. 再执行一次第6步的流程后,请求结束。

注册转换器

SpringMvc

  • 枚举序列化(出参):委托jackson进行序列化,往下看。
  • 枚举反序列化(入参):Get请求通过注册转换器WebMvcConfig,POST请求委托jackson进行反序列化
  • 获取转换器:通过双重循环遍历类型树匹配到转换器

jackson

jackson支持通过@JsonValue注解在枚举上标识序列化和反序列化的字段。

  • 默认枚举序列化:JsonValueSerializer.serialize

  • 默认枚举反序列化:EnumDeserializer.deserialze

  • 获取转换器:通过当前类型查找,没有则通过枚举类型查找一次

    如果默认枚举解析器功能不满足,可以再自定义全局枚举解析器。序列化解析器需要继承JsonSerializer,反序列化需要继承JsonDeserializer, simpleModule.addSerializer(Enum.class, new BaseEnumSerializer());

    再注册进objectMapper中。值得一提的是,jackson是支持在注册时不指定具体的枚举类型,这就会对系统中所有枚举生效。

fastjson:

未查询到类似@JsonValue注解,必须得自定义枚举解析器。jackson,也是支持对所有枚举类进行指定。可以直接重写获取枚举的函数。

mybatis-plus

mybatis-plus支持通过@EnumValue注解在枚举上标识序列化和反序列化的字段。通过实现mybatis提供的TypeHandler接口可以实现自定义解析器,mybatis-plus也是通过MybatisEnumTypeHandler来支持@EnumValue注解的。

自定义枚举转换器,在配置文件中进行配置

hutool

使用hutool提供的BeanUtil.copyProperties属性拷贝工具。在进行属性拷贝的过程中,可能会出现枚举转化的情况。

但并hutool未提供可标识字段的注解,且默认的枚举转换器cn.hutool.core.convert.impl.EnumConverter基本不可用,所以需要自定义转换器。

  • 序列化:枚举转字符串或者数值,需要重写CharacterConverter或者NumberConverter来处理枚举的情况。
  • 反序列化:其他类型转枚举,需要遍历系统中所有存在的枚举类型,挨个进行注册ConverterRegistry.getInstance().putCustom(clazz, new EnumLabelConverter<>(clazz))
  • 获取转换器:对枚举没有做特殊处理 ,需要手动对系统中的所有枚举进行手动注册,官方文档有注册转换器的文章。

easy-excel

hutool类似,并未对枚举进行特殊处理,只能对每个枚举进行注册,推荐在实体字段上增加注解来手动指定转换器(根据label进行转换)

相关推荐
短剑重铸之日7 小时前
《ShardingSphere解读》07 读写分离:如何集成分库分表+数据库主从架构?
java·数据库·后端·架构·shardingsphere·分库分表
wefly20178 小时前
m3u8live.cn 在线M3U8播放器,免安装高效验流排错
前端·后端·python·音视频·前端开发工具
zhanggongzichu9 小时前
小白怎么理解后端分层概念
后端·全栈
stark张宇10 小时前
Golang后端面试复盘:从Swoole到IM架构,如何支撑360w用户的实时消息推送?
后端
小码哥_常10 小时前
从0到1:搭建Spring Boot 3企业级认证授权平台
后端
小码哥_常10 小时前
告别扫库噩梦!Spring Boot+Redis让订单超时管理飞起来
后端
大傻^10 小时前
Spring AI Alibaba 快速入门:基于通义千问的AI应用开发环境搭建
java·人工智能·后端·spring·springai·springaialibaba
IT_陈寒11 小时前
SpringBoot实战:3个隐藏技巧让你的应用性能飙升50%
前端·人工智能·后端
彭于晏Yan11 小时前
MQTT消息服务
spring boot·后端·中间件
程序员Sunday12 小时前
Claude Code 生态爆发:5个必知的新工具
前端·人工智能·后端