openFeign 调用后 返回 出现 application/json 错误

项目场景:

远程调用时返回json格式错误

项目场景:从分页插件式改换为原生分页的时候 通过openFeign调用时发现了问题


问题描述

不需要openFeign 调用的时候 返回的数据和格式是对 通过openFeign 调用后返回 出现 application/json 错误 :

org.springframework.web.client.RestClientException: Error while extracting response for type [cn.cws.framework.core.datasource.util.CwsPage<cn.cws.fulimall.vo.bill.backstage.OrderEntryListVo>] and content type [application/json]

原因分析:

远程调用后 转换为json格式传输时 错误:

  1. JSON 结构与 Java 对象不匹配
  2. RestTemplate 配置问题
  3. 使用正确的类型引用进行 REST 调用
  4. JSON 字段校验
    通过以上的步骤 发现问题出现在这个类 CwsPage 少了一个 setList() 方法
package cn.cws.framework.core.datasource.util;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import lombok.ToString;

import java.util.List;
import java.util.function.Function;

import static java.util.stream.Collectors.toList;


@ToString
@ApiModel(value = "CwsPage",description = "分页返回数据含分页相关数据")
public class CwsPage<T> extends Page<T> {

    public CwsPage() {
        super();
    }

    public CwsPage(long current, long size) {
        super(current, size);
    }

    public CwsPage(long current, long size, long total) {
        super(current, size, total);
    }

    public CwsPage(long current, long size, boolean searchCount) {
        super(current, size, searchCount);
    }

    public CwsPage(long current, long size, long total, boolean searchCount) {
        super(current, size, total, searchCount);
    }

    @Deprecated
    @JsonIgnore
    public long getCurrent() {
        return this.current;
    }

    @Deprecated
    @JsonIgnore
    public long getSize() {
        return this.size;
    }

    @Deprecated
    @JsonIgnore
    public List<T> getRecords() {
        return this.records;
    }
    
    

    /**
     * 兼容前端旧数据,现在使用getCurrent
     * @return
     */

    public Long getPageNum() {
        return super.getCurrent();
    }

    /**
     * 兼容前端旧数据,现在使用getSize
     * @return
     */
    public Long getPageSize() {
        return super.getSize();
    }

    /**
     * 兼容前端旧数据,现在使用getRecords
     * @return
     */
    public List<T> getList() {
        return super.getRecords();
    }
    
    



    public Boolean getLastPage() {
        return super.getPages() == super.getCurrent();
    }

    public Boolean getHasNextPage() {
        return super.getPages() > super.getCurrent();
    }

    public CwsPage<T> setRecords(List<T> records) {
        this.records = records;
        return this;
    }

    public <R> CwsPage<R> convert(Function<? super T, ? extends R> mapper) {
        List<R> collect = this.getList().stream().map(mapper).collect(toList());
        return ((CwsPage<R>) this).setRecords(collect);
    }


}

解决方案:

通过上面原因分析4步骤 把json 进行解析 发现出问题:

package cn.cws.framework.core.datasource.util;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import lombok.ToString;

import java.util.List;
import java.util.function.Function;

import static java.util.stream.Collectors.toList;


@ToString
@ApiModel(value = "CwsPage",description = "分页返回数据含分页相关数据")
public class CwsPage<T> extends Page<T> {

    public CwsPage() {
        super();
    }

    public CwsPage(long current, long size) {
        super(current, size);
    }

    public CwsPage(long current, long size, long total) {
        super(current, size, total);
    }

    public CwsPage(long current, long size, boolean searchCount) {
        super(current, size, searchCount);
    }

    public CwsPage(long current, long size, long total, boolean searchCount) {
        super(current, size, total, searchCount);
    }

    @Deprecated
    @JsonIgnore
    public long getCurrent() {
        return this.current;
    }

    @Deprecated
    @JsonIgnore
    public long getSize() {
        return this.size;
    }

    @Deprecated
    @JsonIgnore
    public List<T> getRecords() {
        return this.records;
    }

    public void setList(List<T> list){
        this.records = list;
    }

    /**
     * 兼容前端旧数据,现在使用getCurrent
     * @return
     */

    public Long getPageNum() {
        return super.getCurrent();
    }

    /**
     * 兼容前端旧数据,现在使用getSize
     * @return
     */
    public Long getPageSize() {
        return super.getSize();
    }

    /**
     * 兼容前端旧数据,现在使用getRecords
     * @return
     */
    public List<T> getList() {
        return super.getRecords();
    }






    public Boolean getLastPage() {
        return super.getPages() == super.getCurrent();
    }

    public Boolean getHasNextPage() {
        return super.getPages() > super.getCurrent();
    }

    public CwsPage<T> setRecords(List<T> records) {
        this.records = records;
        return this;
    }

    public <R> CwsPage<R> convert(Function<? super T, ? extends R> mapper) {
        List<R> collect = this.getList().stream().map(mapper).collect(toList());
        return ((CwsPage<R>) this).setRecords(collect);
    }


}
<think>好的,我现在需要解决Spring Boot中使用Feign调用返回application/octet-stream类型接口的问题。用户希望得到一个示例解决方案。首先,我得回忆一下Feign的基本用法,以及处理不同响应类型的方法。 Feign默认可能使用JSON解析器,比如Jackson,来处理响应。但当接口返回的是application/octet-stream,也就是二进制数据时,比如文件下载,Feign默认的解码器可能无法正确解析,导致错误。这时候需要自定义解码器来处理二进制流。 接下来,我需要确认如何处理这种情况。通常的做法是实现一个自定义的Decoder,将响应体直接转换为byte数组或者InputStream。同时,Feign客户端需要配置使用这个解码器。 另外,可能还需要调整Feign的配置,确保它能够处理octet-stream类型。比如,在@FeignClient注解中指定配置类,或者在配置类中注册自定义的Decoder。 然后,考虑编写示例代码。首先创建一个Feign配置类,定义自定义的Decoder,可能使用Spring的ResponseEntity来包装字节数据。接着,在Feign客户端接口中,指定响应的类型为ResponseEntity<byte[]>,并设置produces为application/octet-stream。 同时,需要注意Feign客户端的依赖是否正确。例如,是否引入了OpenFeign的相关库,以及Spring Cloud的版本兼容性。不过用户的问题可能更多集中在配置和代码示例上,所以依赖问题可能不需要详细展开,但可能需要提及。 还可能存在异常处理的问题,比如如何处理网络错误或无效响应。不过用户可能首先需要一个基础的示例,之后再考虑增强健壮性。 测试部分,如何调用这个Feign客户端并正确获取字节数据,比如保存为文件或者进一步处理。这也需要在示例中体现,比如在Controller中调用Feign客户端,然后将字节数组写入HttpServletResponse输出流。 最后,验证步骤,确保能够正确下载文件,或者处理二进制数据。可能需要使用Mock服务器或者真实的服务端接口进行测试。 总结步骤:配置自定义Decoder,定义Feign客户端接口,正确设置响应类型,处理二进制数据,编写调用示例,并测试验证。</think>在Spring Boot中处理Feign客户端接收$application/octet-stream$类型响应,需要自定义解码器配置。以下是分步解决方案: ### 一、添加依赖 确保$pom.xml$包含OpenFeign依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> ``` ### 二、自定义解码器 创建Feign配置类处理二进制流: ```java @Configuration public class FeignConfig { @Bean public Decoder feignDecoder() { return (response, type) -> { if (byte[].class.equals(type)) { return StreamUtils.copyToByteArray(response.body().asInputStream()); } return new SpringDecoder(new ObjectFactory<>( () -> new HttpMessageConverters(new RestTemplate().getMessageConverters()) )).decode(response, type); }; } } ``` ### 三、定义Feign客户端 ```java @FeignClient( name = "fileClient", url = "${feign.client.url}", configuration = FeignConfig.class ) public interface FileClient { @GetMapping(value = "/download", produces = "application/octet-stream") ResponseEntity<byte[]> downloadFile(); } ``` ### 四、调用示例 ```java @RestController public class FileController { @Autowired private FileClient fileClient; @GetMapping("/download") public void download(HttpServletResponse response) throws IOException { ResponseEntity<byte[]> result = fileClient.downloadFile(); response.setContentType("application/octet-stream"); response.getOutputStream().write(result.getBody()); } } ``` ### 五、关键配置说明 1. 自定义$Decoder$通过判断返回类型为$byte[]$时直接读取输入流 2. 使用$ResponseEntity<byte[]>$确保正确处理响应头信息 3. 必须显式声明$produces = "application/octet-stream"$匹配接口契约 这种方法已成功应用于文件下载、PDF生成等二进制传输场景[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟子涵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值