启动SpringBootGateway失败,发生了依赖冲突
1.问题
在自己搭建的springcloud项目中启动Gateway网关服务时启动失败.控制台打印了如下错误提示:
**********************************************************
Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.
**********************************************************
2023-04-13 12:26:05.476 WARN 9756 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'routeDefinitionRouteLocator' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Unsatisfied dependency expressed through method 'routeDefinitionRouteLocator' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'modifyRequestBodyGatewayFilterFactory' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Unsatisfied dependency expressed through method 'modifyRequestBodyGatewayFilterFactory' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.http.codec.ServerCodecConfigurer' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
2023-04-13 12:26:05.479 INFO 9756 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2023-04-13 12:26:05.492 INFO 9756 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-04-13 12:26:05.611 ERROR 9756 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.
2.原因分析
我在gateway服务的pom文件中引入了自定义的common模块依赖,而在我自定义的common模块中又引入了spring-boot-starter-web的起步依赖,出现了依赖传递.由于Spring Cloud Gateway 是使用 netty+webflux实现,webflux与web是冲突的,最终导致了gateway服务启动失败.
从控制台中的错误提示中,我们可以看到是由于Gateway在初始化配置时,需要一个ServerCodecConfigurer的Bean.
查看org.springframework.cloud.gateway.config.GatewayAutoConfiguration中的源码.
@Bean
@ConditionalOnEnabledFilter
public ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory(ServerCodecConfigurer codecConfigurer) {
return new ModifyRequestBodyGatewayFilterFactory(codecConfigurer.getReaders());
}
可以看到在创建ModifyRequestBodyGatewayFilterFactory 的方法上面有一个@ConditionalOnEnabledFilter注解,进入源码,观察到需要一个OnEnabledFilter.class的字节码文件才符合条件.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnEnabledFilter.class})
public @interface ConditionalOnEnabledFilter {
Class<? extends GatewayFilterFactory<?>> value() default DefaultValue.class;
}
但是引入的SpringMVC起步依赖产生了依赖冲突,环境中没有找到OnEnabledFilter.class字节码文件.最终导致启动失败.
3.解决方案
在gateway服务的pom文件中排除spring-boot-starter-web依赖.