枚举转换踩坑

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

流程分析

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

相关推荐
man20171 小时前
【2024最新】基于springboot+vue的闲一品交易平台lw+ppt
vue.js·spring boot·后端
hlsd#1 小时前
关于 SpringBoot 时间处理的总结
java·spring boot·后端
路在脚下@1 小时前
Spring Boot 的核心原理和工作机制
java·spring boot·后端
幸运小圣2 小时前
Vue3 -- 项目配置之stylelint【企业级项目配置保姆级教程3】
开发语言·后端·rust
前端SkyRain3 小时前
后端Node学习项目-用户管理-增删改查
后端·学习·node.js
提笔惊蚂蚁3 小时前
结构化(经典)软件开发方法: 需求分析阶段+设计阶段
后端·学习·需求分析
老猿讲编程3 小时前
Rust编写的贪吃蛇小游戏源代码解读
开发语言·后端·rust
黄小耶@3 小时前
python如何使用Rabbitmq
分布式·后端·python·rabbitmq
宅小海4 小时前
Scala-List列表
开发语言·后端·scala
蔚一5 小时前
Javaweb—Ajax与jQuery请求
前端·javascript·后端·ajax·jquery