解决Spring Cloud Gateway中使用OpenFeign出现的错误

问题描述

Spring Cloud版本:Hoxton.SR5
Spring Boot 版本:2.3.1.RELEASE


Spring Cloud Gateway 项目中使用了OpenFeign组件,配置引用均正确。报错如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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:

提炼问题:

1
No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters

HttpMessageConverters这个没有被导入

问题解决

查看github问题跟踪
https://github.com/spring-cloud/spring-cloud-openfeign/issues/235

的确需要添加配置,但是怎么配置,由于时间过去久远,就不好查看了。

于是开始源码。HttpMessageConverters.java 中没有发现异常,于是开始查看是否存在AutoConfiguration
打开HttpMessageConvertersAutoConfiguration.java

1
2
3
4
5
6
7
8
@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

1
2
3
4
5
6
7
8
9
10
11
12
    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,最终成功。

1
2
3
4
5
    @Bean
    @ConditionalOnMissingBean
    public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
        return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
    }