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解码器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 剖析Fork join并发框架工作窃取算法

    剖析Fork join并发框架工作窃取算法

    这篇文章主要为大家剖析介绍了Fork join并发框架工作窃取算法的示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • JAVA得到数组中最大值和最小值的简单实例

    JAVA得到数组中最大值和最小值的简单实例

    这篇文章主要介绍了JAVA得到数组中最大值和最小值的简单实例,需要的朋友可以参考下
    2014-08-08
  • 详解MySQL的简易封装以及使用

    详解MySQL的简易封装以及使用

    本文主要介绍了MySQL的简易封装以及使用。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • Spring实战之使用Expression接口进行表达式求值操作示例

    Spring实战之使用Expression接口进行表达式求值操作示例

    这篇文章主要介绍了Spring实战之使用Expression接口进行表达式求值操作,结合实例形式分析了Spring操作Expression接口实现表达式运算的操作技巧与相关注意事项,需要的朋友可以参考下
    2019-12-12
  • Java web网站访问量的统计

    Java web网站访问量的统计

    这篇文章主要为大家详细介绍了Java web网站访问量的统计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • 利用java开发简易版扫雷游戏

    利用java开发简易版扫雷游戏

    这篇文章主要介绍了利用java开发一个丐版扫雷游戏,喜欢玩扫雷的小伙伴们一定要试试哦,对正在学习java开发的小伙伴们也有一定帮助,需要的朋友可以参考下
    2021-04-04
  • JAVA利用接口实现多继承问题的代码实操演示

    JAVA利用接口实现多继承问题的代码实操演示

    Java语言并不支持多继承,这是由于多继承会带来许多复杂的问题,例如"菱形问题"等,下面这篇文章主要给大家介绍了关于JAVA利用接口实现多继承问题的相关资料,需要的朋友可以参考下
    2024-03-03
  • Java BigDecimal中divide方法案例详解

    Java BigDecimal中divide方法案例详解

    这篇文章主要介绍了Java BigDecimal中divide方法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • SpringBoot @ConfigurationProperties注解的简单使用

    SpringBoot @ConfigurationProperties注解的简单使用

    即便现在简化了配置,但是一个独立的配置文件总是易于理解而且使人安心的。Spring在构建完项目后,会默认在resources文件夹下创建一个application.properties文件,application.yml也是一样的效果。@ConfigurationProperties可以获取配置文件中的数据,将其注入类。
    2021-05-05
  • MyBatis入门实例教程之创建一个简单的程序

    MyBatis入门实例教程之创建一个简单的程序

    这篇文章主要介绍了MyBatis入门创建一个简单的程序,在 MySQL 中创建数据库 mybatisdemo,编码为 utf8,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-02-02

最新评论