SpringCloud OpenFeign 自定义响应解码器的问题记录

 更新时间:2024年06月06日 10:40:16   作者:编程海洋  
我们在使用 Spring Cloud 微服务的时候,通常将返回结果使用一个JsonResult 类进行封装,本文重点介绍SpringCloud OpenFeign 自定义响应解码器的问题记录,感兴趣的朋友跟随小编一起看看吧

一、JsonResult 在 OpenFeign 微服务调用的问题

我们在使用 Spring Cloud 微服务的时候,通常将返回结果使用一个JsonResult 类进行封装,例如如下的格式:

public class JsonResult<T> {
    /* 响应码,200为成功   */
    private Integer code;
    /* 失败时的具体失败信息   */
    private String message;
    /* 成功时的数据对象   */
    private T data;
}
 

而调用方在使用Spring Cloud OpenFeign定义的客户端调用远程服务时,由于远程微服务接口的返回值也是 JsonResult 对象,这样本地的接口也需要使用 JsonResult 进行接收,这增加了额外的Result类重新拆开等工作。

有没有办法实现一些自定义的逻辑,比如将统一返回的Result类重新拆开仅返回对应的业务对象,或者对特定的响应码进行处理等等?

二、自定义 OpenFeign 响应解码器

为了实现上述功能,我们就需要改造默认的Decoder。Spring Cloud OpenFeign允许我们在定义一个FeignClient 的时候,指定一个额外的配置类,比如:

@FeignClient(
    name = "xxx-base", 
    path = "/api/base",
    configuration = CustomizedConfiguration.class /* 自定义配置类 */
)
public interface RemoteUserService {
    //..
}

我们可以在 CustomizedConfiguration 中定义一个自己的 Decoder 来覆盖默认的配置。

Spring Cloud 对 Feign的封装和默认配置可以查看官方文档。

自定义的 Decoder 需要实现feign.codec.Decoder接口,也可以参考默认的Decoder的实现逻辑(org.springframework.cloud.openfeign.support.ResponseEntityDecoder),

下面的实现可以对统一返回值Result类的解包,并对异常返回进行处理:

public class CustomizedConfiguration{
    @Bean
    public Decoder feignDecoder() {
        return new OpenFeignResultDecoder();
    }
}
public class OpenFeignResultDecoder implements Decoder {
    @Resource
    ObjectMapper objectMapper;
    @Override
    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
        String resultJson = this.getResponseBody(response);
        try {
            JavaType rawType = objectMapper.getTypeFactory().constructType(type);
            JavaType resultType = objectMapper.getTypeFactory().constructParametricType(JsonResult.class, rawType.getRawClass());
            JsonResult<?> jsonResult = objectMapper.readValue(resultJson, resultType );
            if (jsonResult.getCode() != HttpStatus.OK.value()){
                throw new DecodeException(
                        response.status(),
                        jsonResult.getMessage(),
                        response.request());
            }
            return jsonResult.getData();
        } catch (Exception ex){
            throw new IllegalArgumentException("对象转换失败: " + ex.getMessage());
        }
    }
    /* 
     * 将 response body 解析为 string 
     */ 
    private static String getResponseBody(Response response) throws IOException {
        Response.Body resBody = response.body();
        if (Objects.isNull(resBody)){
            throw new DecodeException(
                    response.status(),
                    "返回体为空",
                    response.request());
        }
        String jsonStr;
        char[] buffer = new char[1024*4];
        int len;
        try (
                Reader reader = resBody.asReader(StandardCharsets.UTF_8);
                StringWriter strWriter = new StringWriter()
        ){
            while ((len = reader.read(buffer)) != -1){
                strWriter.write(buffer, 0, len);
            }
            jsonStr= strWriter.toString();
        }
        return jsonStr;
    }
}

实现了Decoder之后,只需要将其配置到CustomizedConfiguration中即可。

三、为 FeignClient 注册全局配置

注意如果CustomizedConfiguration添加了@Configuration的注解,则会成为Feign Client构建的默认配置,这样就不需要在每个@FeignClient注解中都去指定配置类了:

@Configuration
public class OpenFeignConfig {
    @Bean
    public Decoder feignDecoder() {
        return new OpenFeignResultDecoder();
    }
}
@FeignClient(
    name = "xxx-base",
    path = "/api/base"
)
public interface RemoteUserService {
    //..
}

四、使用 OpenFeign 远程服务示例

添加了自定义的Decoder之后,如果一个远程接口的定义是这样的:

@FeignClient(
    name = "xxx-base",
    path = "/api/base"
)
public interface RemoteUserService {
   @GetMapping(value = "/user/detail/{userId}")
   public User getUserDetailById(@PathVariable Integer userId)
}
// ...
@Resource
RemouteUserService userService
public void demoUserService(int userId){
    User user = userService.getUserDetailById(userId);
    // ....
} 
 

到此这篇关于SpringCloud OpenFeign 自定义响应解码器的文章就介绍到这了,更多相关SpringCloud OpenFeign解码器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java分布式基于RestTemplate的使用方法

    java分布式基于RestTemplate的使用方法

    这篇文章主要为大家介绍了java分布式基于RestTemplate的使用方法说明,有需要的朋友可以借鉴参考下希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-02-02
  • maven中的maven-antrun-plugin插件示例详解

    maven中的maven-antrun-plugin插件示例详解

    maven-antrun-plugin 是 Maven 生态中一个强大的工具,尤其适合需要复用 Ant 脚本或实现复杂构建逻辑的场景,然而,过度使用可能导致构建脚本复杂化,建议权衡利弊后合理使用,这篇文章主要介绍了maven中的maven-antrun-plugin插件详解,需要的朋友可以参考下
    2025-06-06
  • IDEA的Terminal无法执行git命令问题

    IDEA的Terminal无法执行git命令问题

    这篇文章主要介绍了IDEA的Terminal无法执行git命令问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Java 数组的两种初始化方式

    Java 数组的两种初始化方式

    这篇文章主要介绍了Java 数组的两种初始化方式,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-02-02
  • springboot如何获取请求者的ip地址

    springboot如何获取请求者的ip地址

    在Spring框架中,可以使用拦截器(Interceptor)来监听每个控制器(Controller)的请求,并记录请求者的IP地址,这篇文章主要介绍了springboot如何获取请求者的ip地址,需要的朋友可以参考下
    2024-07-07
  • Maven忽略单元测试及打包到Nexus的实现

    Maven忽略单元测试及打包到Nexus的实现

    我们的工程在打包发布时候,通常都需要忽略单元测试,以免因环境原因,无法通过单元测试而影响发布,本文主要介绍了Maven忽略单元测试及打包到Nexus的实现,感兴趣的可以了解一下
    2024-04-04
  • logback中显示mybatis查询日志文件并写入的方法示例

    logback中显示mybatis查询日志文件并写入的方法示例

    这篇文章主要为大家介绍了logback中显示mybatis查询日志文件并写入的方法示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • hibernate 配置数据库方言的实现方法

    hibernate 配置数据库方言的实现方法

    这篇文章主要介绍了hibernate 配置数据库方言的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • IDEA配置Tomcat后,控制台tomcat catalina log出现乱码问题

    IDEA配置Tomcat后,控制台tomcat catalina log出现乱码问题

    本文介绍了如何通过设置Tomcat和IDEA的编码格式来解决编码问题,首先尝试修改Tomcat的logging.properties文件中的编码设置,如果未解决问题,则调整IDEA的编码设置,通过修改vmoptions文件来全局设置IDEA的编码格式,作者分享了个人成功解决问题的方法和步骤,供其他开发者参考
    2024-09-09
  • logback如何自定义日志存储

    logback如何自定义日志存储

    这篇文章主要介绍了logback如何自定义日志存储的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08

最新评论