Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.
后台-插件-广告管理-内容页头部广告(手机) |
一、问题
在启动springcloud的gateway模块的时候报错Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.
二、问题产生的原因
gateway组件中的 spring-boot-starter-webflux 和 springboot作为web项目启动必不可少的 spring-boot-starter-web 出现冲突。
三、解决方案(任选一种就可以)
3.1 注释pom.xml内容
在gateway的pom文件上注释掉spring-boot-starter-web代码
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
3.2修改配置文件
在配置文件上加上
- spring:
- main:
- web-application-type: reactive
解释:这里面涉及到springboot的启动流程因为spring-boot-starter-webflux包,在springboot启动类型里面表示的就是reactive。我们可以看源码,了解一下springboot启动流程
一步一步点进去
这是springApplication构造方法,我们先看构造方法
点进去
3.2.1通过springboot源码解释
springApplication构造源码(不同版本会有差异,当前版本是2.6.1)
- public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
- this.sources = new LinkedHashSet();
- // 在控制台打印banner.txt文本内容
- this.bannerMode = Mode.CONSOLE;
- this.logStartupInfo = true;
- this.addCommandLineProperties = true;
- this.addConversionService = true;
- this.headless = true;
- this.registerShutdownHook = true;
- this.additionalProfiles = Collections.emptySet();
- this.isCustomEnvironment = false;
- this.lazyInitialization = false;
- this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
- this.applicationStartup = ApplicationStartup.DEFAULT;
- // 开始输resourceLoader注入了属性null
- this.resourceLoader = resourceLoader;
- Assert.notNull(primarySources, "PrimarySources must not be null");
- //将启动类从数组重新封装Set,注入到primarySources当中
- this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
- /**
- *webApplicationType有三种类型,REACTIVE,SERVLET,NONE
- * 引入spring-boot-starter-web就是SERVLET
- * 引入spring-boot-starter-webflux就是REACTIVE
- * 没有就是NONE
- */
- this.webApplicationType = WebApplicationType.deduceFromClasspath();
- /**
- *从spring-cloud-context的jar包的META-INF/spring.factories文件中得到key为org.springfra *mework.boot.BootstrapRegistryInitializer的全类名集合,进行实例化,然后注入 bootstrapRegi
- *stryInitializers 属性,其中核心方法getSpringFactoriesInstances
- *下面有getSpringFactoriesInstances方法源码详解
- *这里简单的解释一下getSpringFactoriesInstances方法就是从META-INF/spring.factories读取配
- *置文件
- */
- this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
- /**
- *依然调用getSpringFactoriesInstances方法
- *从spring-boot的jar包的META-INF/spring.factories文件中得到key为org.springframework. *context.ApplicationContextInitializer的全类名集合,然后进行实例化,然后注入initializers
- *(初始化容器集合)属性
- */
- this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
- //跟上面一样,这里是得到监听器的集合,并注入
- this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
- //获取当前的main方法运行的类,也就是我们的主类
- this.mainApplicationClass = this.deduceMainApplicationClass();
- }
上面说的META-INF/spring.factories都是在springboot.jar包中,不过BootstrapRegistryInitializer是在spring-cloud-context中。
3.2.2了解getSpringFactoriesInstances方法
随便选一个点进去
- private
Collection getSpringFactoriesInstances(Class type, Class<?>[] parameterTypes, Object... args) { - ClassLoader classLoader = this.getClassLoader();
- /** SpringFactoriesLoader.loadFactoryNames(type, classLoader)这里才是核心,
- *这个方法会扫描所有jar包类路径下 META-INF/spring.factories
- */
- Set
names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); - List
instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); - AnnotationAwareOrderComparator.sort(instances);
- return instances;
- }
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。
在线投稿:投稿 站长QQ:1888636
后台-插件-广告管理-内容页尾部广告(手机) |