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解码器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
java8 filter方法、Predicate接口的使用方式
这篇文章主要介绍了java8 filter方法、Predicate接口的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-07-07SpringMVC使用hibernate-validator进行参数校验最佳实践记录
这篇文章主要介绍了SpringMVC使用hibernate-validator进行参数校验最佳实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2021-05-05springboot使用redis对单个对象进行自动缓存更新删除的实现
本文主要介绍了springboot使用redis对单个对象进行自动缓存更新删除的实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2021-08-08
最新评论