spring-boot-devtools是个好东西,在开发调试时可以随时热部署,不用每次手工启停。前两天一个项目查log,发现总有这样的错误日志输出:
org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:90) at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:184) at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163) at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:552) at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:67) at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:45) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:122) at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:68) at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) at org.test.Application.main(Application.java:15) |
看一下项目的主体结构,大致是这样的,我做了简化:
首先是spring boot的启动入口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package org.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.Banner.Mode;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication public class Application {
public static void main(String[] args) {
try {
SpringApplication app = new SpringApplication(Application. class );
app.setBannerMode(Mode.OFF);
app.setWebEnvironment( false );
app.run(args);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
} |
主服务大致是这样的(已简化):
1
2
3
4
5
6
7
8
9
10
11
12
|
package org.test;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Service;
@Service public class MainService {
@PostConstruct
public void startServer() {
System.out.println( "START" );
}
} |
只要一启动,就会报上面的错误,但实际上又不影响任何功能,devtools的热部署功能也仍然生效。对比以前的项目查了查,发现问题出在main()方法上,SpringApplication.run()一但放到try...catch块里就会导致devtools抛个异常。把main()里的try...catch去掉,或者把app.run(args)这句移出try...catch,或者catch到异常不要printStackTrace(),再运行就不会有错误日志了。
具体原因等有空了再去翻源码吧,对spring boot来说,启动时try...catch真的是多此一举。