IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 记录使用fastjson消息转换器遇到的问题和解决方法 -> 正文阅读

[开发测试]记录使用fastjson消息转换器遇到的问题和解决方法

记录使用fastjson消息转换器遇到的问题和解决方法


前言

实际项目场景中想使用fastjson做消息转换器来解决一些类型转换的问题,随着后面踩到的坑也比较多,还好也是一个个解决了


一、定义一个简单的fastjson消息转换器

自定义一个配置类FastJsonConfig添加到HttpMessageConverters中,可以在配置类里过滤或者修改序列化的内容

@Configuration
public class FastJsonMessageConvertConfig {
    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters(){
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig =  new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        converter.setFastJsonConfig(fastJsonConfig);
        return new HttpMessageConverters(converter);
    }
}

二、来需求了

1.在某一个字段中指定修改它的类型

通过注解的方式实现

@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ConvertField {
    Class<?> value() default int.class;
}

这里更换了一下方式,通过实现WebMvcConfigurer接口,重载extendMessageConverters方法并把自定义的配置类FastJsonConfig添加到这里面去。通过ValueFilter去修改字段的值

@Slf4j
@Configuration
public class FastJsonMessageConvertConfig implements WebMvcConfigurer {
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig =  new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        fastJsonConfig.setSerializeFilters((ValueFilter) (object, name, value) -> {
            try {
                Field field = object.getClass().getDeclaredField(name);
                ConvertField annotation = field.getAnnotation(ConvertField.class);
                if (Objects.isNull(annotation)) {
                    return value;
                }
                return Convert.convert(annotation.value(),value);
            } catch (NoSuchFieldException ignore) {
            	return value;
            }
            return value;
        });
        converter.setFastJsonConfig(fastJsonConfig);
        converters.add(converter);
    }
}

这样就可以任意转换你想要的类型了,比如下面字符串类型的字段在序列化时转为int
在这里插入图片描述

三、出bug啦

1.fastjson消息转换器失效

这里排查问题排查了很久。通过断点慢慢去看,发现HttpMessageConverter里添加的消息转换器messageConverters有两个MappingJackson2HttpMessageConverter,在遍历converters时首先经过jackson进行转换就不再走fastjson了,从而导致fastjson中@JSONField失效以及自定义的@ConvertField都失效了
在这里插入图片描述

解决方法:

首先通过Iterator方式从converters移除这两个MappingJackson2HttpMessageConverter,(不知道还有没有用处的情况下)也可以利用容器暂存起来,然后把fastjson添加进去,再把暂存的两个MappingJackson2HttpMessageConverter重新添加进去,简单理解就是给jackson和fastjson的执行顺序换了一下

@Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 首先移除jackson2的影响,用别的容器暂存
        Iterator<HttpMessageConverter<?>> iterator = converters.iterator();
        Set<HttpMessageConverter<?>> set = new ConcurrentHashSet<>();
        while (iterator.hasNext()) {
            HttpMessageConverter<?> converter = iterator.next();
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                set.add(converter);
                iterator.remove();
            }
        }
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        fastJsonConfig.setSerializeFilters((ValueFilter) (object, name, value) -> {
            try {
                Field field = object.getClass().getDeclaredField(name);
                ConvertField annotation = field.getAnnotation(ConvertField.class);
                if (Objects.isNull(annotation)) {
                    return value;
                }
                return Convert.convert(annotation.value(), value);
            } catch (NoSuchFieldException ignore) {
            }
            return value;
        });
        converter.setFastJsonConfig(fastJsonConfig);
        // 添加fastjson
        converters.add(converter);
        // 从容器中暂存的jackson2放回来
        for (HttpMessageConverter<?> temp : set) {
            if (temp instanceof MappingJackson2HttpMessageConverter) {
                converters.add(temp);
            }
        }
    }

这样执行顺序就会从fastjson开始
在这里插入图片描述

2.自定义@ConvertField注解失效

想法是利用@JSONField修改序列化后的字段名称,利用自定义@ConvertField修改字段类型。

通过第一点修改后fastjson转换器生效,@JSONField注解也生效,但自定义@ConvertField却失效了

在这里插入图片描述
请求接口后返回的结果:
在这里插入图片描述
可以看出@JSONField注解生效,machineTypeId确实改为machineType了,但是字段类型并没有被修改

又通过打断点慢慢去看,最终发现在ValueFilter的lamda表达式中有个name,这个name对应的是返回实体类对应的属性名称,但此时的属性名称已经通过@JSONField从machineTypeId修改为machineType了,而object存储的实体里对应的还是machineTypeId,字段名没有对应上所以没有类型转换在这里插入图片描述

解决方法:

在name获取对应的(已经从@JSONFiled转换后)的实体类名时再次给它转换一下,让它与object中的实体属性名对应

 private static final Map<String, String> map = new HashMap<>();

    static {
        map.put("machineType", "machineTypeId");
    }

    private String convertClassAttributeName(String name) {
        if (map.containsKey(name)) {
            return map.get(name);
        }
        return name;
    }

调用方法
在这里插入图片描述
解决问题!
在这里插入图片描述

总结

如果有更好处理方式的,欢迎各位指出,希望对大家有所帮助!

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 19:07:17  更:2022-04-22 19:08:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 10:20:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码