枚举转换踩坑

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

流程分析

  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进行转换)

相关推荐
章豪Mrrey nical3 小时前
前后端分离工作详解Detailed Explanation of Frontend-Backend Separation Work
后端·前端框架·状态模式
派大鑫wink4 小时前
【JAVA学习日志】SpringBoot 参数配置:从基础到实战,解锁灵活配置新姿势
java·spring boot·后端
程序员爱钓鱼5 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
xUxIAOrUIII5 小时前
【Spring Boot】控制器Controller方法
java·spring boot·后端
Dolphin_Home5 小时前
从理论到实战:图结构在仓库关联业务中的落地(小白→中级,附完整代码)
java·spring boot·后端·spring cloud·database·广度优先·图搜索算法
zfj3215 小时前
go为什么设计成源码依赖,而不是二进制依赖
开发语言·后端·golang
weixin_462446235 小时前
使用 Go 实现 SSE 流式推送 + 打字机效果(模拟 Coze Chat)
开发语言·后端·golang
JIngJaneIL5 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
小信啊啊6 小时前
Go语言切片slice
开发语言·后端·golang
Victor3567 小时前
Netty(20)如何实现基于Netty的WebSocket服务器?
后端