欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

SpringCloudOpenFeign自定义响应解码器的问题记录,

来源: javaer 分享于  点击 42075 次 点评:228

SpringCloudOpenFeign自定义响应解码器的问题记录,


目录
  • 一、JsonResult 在 OpenFeign 微服务调用的问题
  • 二、自定义 OpenFeign 响应解码器
  • 三、为 FeignClient 注册全局配置
  • 四、使用 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解码器内容请搜索3672js教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持3672js教程!

您可能感兴趣的文章:
  • SpringCloud OpenFeign自定义结果解码器方式
  • springcloud引入spring-cloud-starter-openfeign失败的解决
  • 完美解决SpringCloud-OpenFeign使用okhttp替换不生效问题
  • SpringCloud OpenFeign Post请求400错误解决方案
  • SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法
相关栏目:

用户点评