OpenFeign 使用FastJson解析返回数据

在微服务项目中,一个服务需要调用另一个服务来获取相关数据,feign组件能够很方便进行调用,添加相关依赖和注解,就能快速进行使用。

在实际应用中,调用完之后需要解析返回的数据,这时候就有一个问题, 如果是多层封装的数据

,如何进行获取?第一时间想到的是直接强转,这样做如果只是简单的返回对象是没有问题的,但需要的数据是对象中集合,而直接强转获取到的集合并不能直接进行操作,这时候就不得不换一种方式。可以把feign调用想象成http调用,而http返回的数据格式是json,那么能不能用json去解析feign返回数据?如果可以就能直接使用FastJson转换成我们需要的集合再进行操作,然鹅使用FastJson解析过程中出现了问题,debug发现返回的数据根本就不是json数据,FastJson直接抛出解析异常,问题在哪就解决问题,返回的数据不是json,那么就让它返回json数据不就能继续往下操作吗?那么如何让feign返回我们需要的json数据呢!!!

查阅相关资料发现(找度娘),因为Feign并不共用Spring MVC的消息转换器链,默认使用的是Jackson Json解析库。只要我们把服务端和客户端都替换成FastJson,理论上就能够返回json数据。

所以来进行配置吧

服务端配置,也就是提供服务的一方

@Configuration
public class FastJsonConverterConfig extends WebMvcConfigurationSupport {

    /**
     * 使用fastjson代替jackson
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        //先把JackSon的消息转换器删除.
        //(1)源码分析可知,返回json的过程为:
        //  Controller调用结束后返回一个数据对象,for循环遍历conventers,找到支持application/json的HttpMessageConverter,然后将返回的数据序列化成json。
        //  具体参考org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法
        //(2)由于是list结构,我们添加的fastjson在最后。因此必须要将jackson的转换器删除,不然会先匹配上jackson,导致没使用fastjson
        for (int i = converters.size() - 1; i >= 0; i--) {
            if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
                converters.remove(i);
            }
        }

        //自定义fastjson配置
        FastJsonConfig config = new FastJsonConfig();
        config.setSerializerFeatures(
                // 是否输出值为null的字段,默认为false,我们将它打开
                SerializerFeature.WriteMapNullValue,
                // 将Collection类型字段的字段空值输出为[]
                SerializerFeature.WriteNullListAsEmpty,
                // 将字符串类型字段的空值输出为空字符串
                SerializerFeature.WriteNullStringAsEmpty,
                // 将数值类型字段的空值输出为0
                SerializerFeature.WriteNullNumberAsZero,
                SerializerFeature.WriteDateUseDateFormat,
                // 禁用循环引用
                SerializerFeature.DisableCircularReferenceDetect
        );

        // 添加支持的MediaTypes;不添加时默认为*/*,也就是默认支持全部
        // 但是MappingJackson2HttpMessageConverter里面支持的MediaTypes为application/json
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON);
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);

        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        fastJsonHttpMessageConverter.setFastJsonConfig(config);
        fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
        converters.add(fastJsonHttpMessageConverter);
        //支持XML格式的请求
        converters.add(new StringHttpMessageConverter());
    }

    /**
     * 发现如果继承了WebMvcConfigurationSupport,则在yml中配置的相关内容会失效。 需要重新指定静态资源
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations(
                "classpath:/static/");
        registry.addResourceHandler("swagger-ui.html").addResourceLocations(
                "classpath:/META-INF/resources/");
        registry.addResourceHandler("doc.html").addResourceLocations(
                "classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations(
                "classpath:/META-INF/resources/webjars/");
        super.addResourceHandlers(registry);
    }

}

客户端配置,也就是调用的一方

@Configuration
public class FeignSimpleEncoderConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        //这里记录所有,根据实际情况选择合适的日志level
        return Logger.Level.FULL;
    }

    @Bean
    public Encoder feignEncoder() {
        return new SpringEncoder(feignHttpMessageConverter());
    }

    @Bean
    public Decoder feignDecoder() {
        return new SpringDecoder(feignHttpMessageConverter());
    }

    /**
     * 设置解码器为fastjson
     *
     * @return
     */
    private ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter());
        return () -> httpMessageConverters;
    }

    private FastJsonHttpMessageConverter getFastJsonConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

        List<MediaType> supportedMediaTypes = new ArrayList<>();
        MediaType mediaTypeJson = MediaType.valueOf(MediaType.APPLICATION_JSON_UTF8_VALUE);
        supportedMediaTypes.add(mediaTypeJson);
        converter.setSupportedMediaTypes(supportedMediaTypes);
        FastJsonConfig config = new FastJsonConfig();
        config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer());
        config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        converter.setFastJsonConfig(config);

        return converter;
    }
}

feign调用类指定配置

//远程调用
@FeignClient(value = "nakadai",fallback = NakadaiClientImpl.class,configuration = FeignSimpleEncoderConfig.class)
@Component
@Headers("Accept: application/json")
public interface NakadaiClient {

    /**
     * 查询数据
     */
    @Headers({"Content-Type: application/json","Accept: application/json"})
    @GetMapping(value = "/nakadai/nakadai/order/getCustomerOrder",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    R getCustomerOrder(@RequestParam("id") Integer id);

}

再重新启动,debug可以发现返回的数据符合json格式,接下来就可以对json数据进行操作了

例:

R result= nakadaiClient.getCustomerOrder(id);
Object orderList = customerOrder.get("orderList");
String jsonString = JSON.toJSONString(orderList);
List<Order> orders = JSON.parseArray(jsonString, Order.class);

这样转换虽然较为麻烦,但操作集合时就没有直接强转所导致的问题

在实际运用中,又发现了一个问题,在服务端配置完之后,发现返回格式全都乱码了,导致无法正确获取接口返回数据,然鹅将这个配置类删除,feign返回数据还是json格式,这说明服务端并不需要去进行配置,配置反而会有问题,发现乱码之后直接将配置类删除即可

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 Java 中的 `JSONObject` 和 `JSONArray` 类来读取和解析 JSON 文件。下面是一个简单的示例代码: ```java import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONException; import java.nio.file.Files; import java.nio.file.Paths; public class JSONParser { public static void main(String[] args) { try { // 读取 JSON 文件内容 String jsonContent = new String(Files.readAllBytes(Paths.get("data.json"))); // 创建 JSONObject JSONObject jsonObject = new JSONObject(jsonContent); // 获取各个字段的值 String name = jsonObject.getString("name"); int age = jsonObject.getInt("age"); boolean isStudent = jsonObject.getBoolean("isStudent"); // 创建 JSONArray JSONArray hobbiesArray = jsonObject.getJSONArray("hobbies"); // 遍历数组并获取值 for (int i = 0; i < hobbiesArray.length(); i++) { String hobby = hobbiesArray.getString(i); System.out.println(hobby); } } catch (JSONException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } ``` 上述代码假设你有一个名为 "data.json" 的 JSON 文件。在代码中,我们首先读取 JSON 文件的内容,然后创建一个 `JSONObject` 对象,并通过键名来获取各个字段的值。如果字段的值是一个数组,我们可以使用 `getJSONArray` 方法获取该数组,并遍历数组获取每个元素的值。 需要注意的是,上述代码使用了 `org.json` 包来处理 JSON 数据。你可以在项目中引入此包,或者使用其他 JSON 处理库,如 Jackson、Gson 等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值