解决SpringCloud Gateway采用OpenFeign远程调用失败的问题
作者:Ramboooooooo
一、框架版本
Spring Boot、 Spring Cloud 、 Spring Cloud Alibaba
框架名称 | 框架版本 |
---|---|
Spring Boot | 2.2.5.RELEASE |
Spring Cloud | Hoxton.SR3 |
Spring Cloud Alibaba | 2.2.1.RELEASE |
二、源码展示
远程鉴权 Controller
控制器代码片段
@RestController @Slf4j @RequestMapping("/security") public class AuthenticationController { @Resource private AuthenticationService authenticationService; @PostMapping("/auth") public Boolean checkAuth(@RequestBody @Valid BaseRequest baseRequest) { log.info("<-------------------------->"); return authenticationService.checkAuth(baseRequest); } }
网关引用 OpenFeign
依赖
<!-- OpenFeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.2.RELEASE</version> </dependency>
网关 OpenFeign
调用客户端
@Component @FeignClient(value = "rms-security-service") public interface InvokeSecurityServiceClient { @PostMapping("/security/auth") Boolean checkAuth(BaseRequest baseRequest); }
三、问题描述
在网关层进行统一鉴权和认证的过程中,需要远程调用鉴权服务器的接口进行鉴权的操作。
但是在采用 OpenFiegn
进行远程调用的过程中,出现了如下的报错堆栈,导致了远程调用失败
- 堆栈信息
feign.codec.EncodeException: No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:384)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ cn.com.jstec.open.cloud.gateway.config.SecurityConfig$$Lambda$772/0x0000016c006c3040 [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/open-platform/achievement/list?page=1" [ExceptionHandlingWebHandler]
Stack trace:
- 关键信息
No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters
四、解决方案
堆栈分析
HttpMessageConverters
没有被注入到容器中管理ISSUES
跟踪- 点击此处 查看
issues
信息
解决方案
源码:HttpMessageConverters.java
中没有发现异常,于是开始查看是否存在 AutoConfiguration
打开 HttpMessageConvertersAutoConfiguration.java
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(HttpMessageConverter.class) @Conditional(NotReactiveWebApplicationCondition.class) @AutoConfigureAfter({ GsonAutoConfiguration.class, JacksonAutoConfiguration.class, JsonbAutoConfiguration.class }) @Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class, JsonbHttpMessageConvertersConfiguration.class }) public class HttpMessageConvertersAutoConfiguration { }
源码:@Conditional(NotReactiveWebApplicationCondition.class)
@Conditional
是 Spring4
新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册 bean
再查看类 NotReactiveWebApplicationCondition
static class NotReactiveWebApplicationCondition extends NoneNestedConditions { NotReactiveWebApplicationCondition() { super(ConfigurationPhase.PARSE_CONFIGURATION); } @ConditionalOnWebApplication(type = Type.REACTIVE) private static class ReactiveWebApplication { } }
Spring Cloud Gateway
是基于 WebFlux
的,是 ReactiveWeb
,所以 HttpMessageConverters
不会自动注入。
于是自己在配置文件中,直接复制源码的 Bean
,最终成功。
# 新建配置类 @Configuration public class WebFluxWithOpenFeignConfig { @Bean @ConditionalOnMissingBean public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) { return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList())); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。