SpringCloud OpenFeign自定义结果解码器方式

 更新时间:2023年09月01日 09:57:14   作者:david'fantasy  
这篇文章主要介绍了SpringCloud OpenFeign自定义结果解码器方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

SpringCloud OpenFeign自定义结果解码器

我们在定义微服务接口的时候,通常会使用一个Result类进行封装,将提示信息,返回对象和状态码等内容封装到一起返回给调用方,

例如

如下的格式:

public class Result<T> {
    /**
     * 响应码,200为成功
     */
    private Integer code;
    /**
     * 失败时的具体失败信息
     */
    private String message;
    /**
     * 失败信息是否为用户提示,如果是的话框架不会主动拦截该错误
     */
    private boolean userPrompt;
    /**
     * 响应的具体对象
     */
    private T data;
}

而调用方在使用Spring Cloud OpenFeign定义的客户端调用远程服务时,默认的解码器只能按照定义的方法返回类型对接口的返回结果进行强制转换,没办法实现一些自定义的逻辑,比如将统一返回的Result类重新拆开,仅返回对应的业务对象,或者对特定的响应码进行处理等等。

为了实现上述功能,我们就需要改造默认的Decoder。

Spring Cloud OpenFeign允许我们在定义一个Feign Client的时候,指定一个额外的配置类,比如:

@FeignClient(name = "stores", configuration = CustomizedConfiguration.class)
public interface StoreClient {
    //..
}

而这个配置类就可以作为我们的扩展点,我们可以在CustomizedConfiguration中定义一个自己的Decoder来覆盖默认的配置。

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

自定义的Decoder需要实现feign.codec.Decoder接口,也可以参考默认的Decoder的实现逻辑(org.springframework.cloud.openfeign.support.ResponseEntityDecoder),下面的实现可以对统一返回值Result类的拆分,并对异常返回进行处理:

public class FeignResultDecoder implements Decoder {
    @Override
    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
        if (response.body() == null) {
            throw new DecodeException(response.status(), "没有返回有效的数据", response.request());
        }
        String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
        //对结果进行转换
        Result result = (Result) JsonUtil.json2obj(bodyStr, type);
        //如果返回错误,且为内部错误,则直接抛出异常
        if (result.getCode() != ResultCode.SUCCESS.code) {
            if (!result.isUserPrompt()) {
                throw new DecodeException(response.status(), "接口返回错误:" + result.getMessage(), response.request());
            }
        }
        return result.data;
    }
}

其中如何将response中的json转换为实际的返回类型很费了一些功夫,因为可能存在复杂的嵌套关系和泛型定义,最后才发现jackson框架已经有默认的实现了…

代码如下:

public static <T> T json2obj(String jsonStr, Type targetType) {
        try {
            JavaType javaType = TypeFactory.defaultInstance().constructType(targetType);
            return mapper.readValue(jsonStr, javaType);
        } catch (IOException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        }
    }

实现了Decoder之后,只需要将其配置到CustomizedConfiguration中即可,注意如果CustomizedConfiguration添加了@Configuration的注解,则会成为Feign Client构建的默认配置,这样就不需要在每个@FeignClient注解中都去指定配置类了:

public class CustomizedConfiguration{
    @Bean
    public Decoder feignDecoder() {
        return new FeignResultDecoder();
    }
}

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

@GetMapping("/api/user/detail")
 public Result<User> detailById(@RequestParam("id") Integer id) {
        User user = userService.getById(id);
        return ResultGenerator.genSuccessResult(user);
 }

我们定义Feign Client方法的时候,方法的返回值可以直接使用Result的泛型类型:

 @RequestMapping(value = "/api/user/detail", method = RequestMethod.GET)
 public User detailById(@RequestParam("id") Integer id)

类似的方式,我们还可以自定义Feign的Encoder,ErrorDecoder等关键配置组件。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决spring中redistemplate不能用通配符keys查出相应Key的问题

    解决spring中redistemplate不能用通配符keys查出相应Key的问题

    这篇文章主要介绍了解决spring中redistemplate不能用通配符keys查出相应Key的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • SpringBoot配置logback的步骤

    SpringBoot配置logback的步骤

    这篇文章主要介绍了SpringBoot配置logback的步骤,帮助大家更好的理解和使用SpringBoot框架,感兴趣的朋友可以了解下
    2020-09-09
  • 在SpringBoot中使用lombok的注意事项

    在SpringBoot中使用lombok的注意事项

    这篇文章主要介绍了在SpringBoot中使用lombok的注意事项,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • maven环境变量配置讲解

    maven环境变量配置讲解

    这篇文章主要介绍了maven环境变量配置讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++/java 继承类的多态详解及实例代码

    C++/java 继承类的多态详解及实例代码

    这篇文章主要介绍了C++/java 继承类的多态详解及实例代码的相关资料,需要的朋友可以参考下
    2017-02-02
  • Maven Settings.xml的基本语法详解

    Maven Settings.xml的基本语法详解

    这篇文章主要为大家介绍了Maven Settings.xml的基本语法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Java Stream map, Collectors(toMap, toList, toSet, groupingBy, collectingAndThen)使用案例

    Java Stream map, Collectors(toMap, toLis

    这篇文章主要介绍了Java Stream map, Collectors(toMap, toList, toSet, groupingBy, collectingAndThen)使用案例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • 关于Spring Cloud健康检查的陷阱

    关于Spring Cloud健康检查的陷阱

    这篇文章主要介绍了关于Spring Cloud健康检查的陷阱,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 使用@Validated注解进行校验却没有效果的解决

    使用@Validated注解进行校验却没有效果的解决

    这篇文章主要介绍了使用@Validated注解进行校验却没有效果的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • SpringBoot整合Druid数据库连接池的方法

    SpringBoot整合Druid数据库连接池的方法

    Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。这篇文章主要介绍了SpringBoot整合Druid数据库连接池的方法,需要的朋友可以参考下
    2020-07-07

最新评论