温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

SpringBoot项目启动但没有监听端口该怎么办

发布时间:2021-09-29 14:20:50 来源:亿速云 阅读:1089 作者:柒染 栏目:编程语言

SpringBoot项目启动但没有监听端口该怎么办,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

前提

我们的这个SpringBoot项目依赖Dubbo、RocketMQ、Nacos等,偶尔有一天发现启动后没有注册到SpringBootAdmin里面,于是检查原因网上搜索资料,找到这篇文章springboot项目正常启动运行,但端口监听不到 的事件与解决方案情况类似,我们的项目里面启动后也在线程里面启动了死循环,如下:

    @PostConstruct
    public void init() {
        log.info("==============初始化==============start");
        try {
            //这里有一段代码在线程里面开启死循环
            xxx.xxx
        } catch (Exception e) {
            log.error("", e);
        }
    }

参考那个文章说的,可能是还没等监听端口然后这边就一直运行死循环了所以要把这段开启多线程内死循环的代码延迟一点启动,改动如下:

@Slf4j
@Component
//这里按顺序排到第10
@Order(value = 10)
public class InitRunner implements ApplicationRunner {

    @Override
    public void run() {
        log.info("==============初始化==============start");
        try {
            //这里有一段代码在线程里面开启死循环
            xxx.xxx
        } catch (Exception e) {
            log.error("", e);
        }
    }
}

测试启动,还是不行,看来不是这里的问题。继续查询资料看到这篇文章SpringBoot内置Tomcat启动时间,既然Tomcat没监听端口那就调试一下看看程序走到那里就没去监听端口了。

调试到关键代码:

class:AbstractApplicationContext
   
    @Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

这里的onRefresh();方法调用了本类里面的onRefresh()方法,看注释:

	/**
	 * Template method which can be overridden to add context-specific refresh work.
	 * Called on initialization of special beans, before instantiation of singletons.
	 * <p>This implementation is empty.
	 * @throws BeansException in case of errors
	 * @see #refresh()
	 */
	protected void onRefresh() throws BeansException {
		// For subclasses: do nothing by default.
	}

翻译一下大致意思是:

模板方法,可以重写该方法以添加特定于上下文的刷新工作。在初始化特殊bean时调用,然后实例化单例。

此实现为空。

看一下这个方法有以下结果实现:

SpringBoot项目启动但没有监听端口该怎么办

很明显应该调用ServletWebServerApplicationContext里面的实现,但我下了断点调试竟然没有进入到这个方法:

	@Override
	protected void onRefresh() {
		super.onRefresh();
		try {
			createWebServer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start web server", ex);
		}
	}

而是直接调了这个空方法:

SpringBoot项目启动但没有监听端口该怎么办

真神奇。

找了个正常的项目,果然是进入到ServletWebServerApplicationContext里面了。然后了两个项目的差别,真的是太乌龙了。

我这个项目并没有依赖spring-boot-starter-web

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

加上这一段试试,果然可以了。

2021-04-15 10:33:52.538 [main] INFO [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start: 204] - Tomcat started on port(s): 8080 (http) with context path ''
2021-04-15 10:33:52.546 [main] INFO [org.springframework.boot.StartupInfoLogger.logStarted: 61] - Started XXXMainApplication in 59.654 seconds (JVM running for 64.354)

可能是当初我考虑到这个项目用Dobbo而不需要spring-web所以就没依赖。后来添加了SpringBootAdmin监控这个是要项目启动端口然后SpringBootAdmin去调用接口查询信息的,然后忘了添加这个依赖。真的是个大乌龙,不过从调试源码也学到了一些东西,感觉源码真是个好东西。

关于SpringBoot项目启动但没有监听端口该怎么办问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI