1 背景
我们在实际的项目开发过程中,会用到数据的处理,数据的初始化等非web的项目,但是又想使用springboot带给我们的方便性
2 方案
我们会从不同的方案来解决实际的问题
2.1 方案一
pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
通过上诉我们可以看到我们引入了web项目
application.yaml文件
spring:
application:
name: demo
#非web的方式运行
main:
web-application-type: none
server:
port: 8080
@PostConstruct完成任务
public class DemoApplication {
@PostConstruct
public void init(){
System.out.println("我是初始化方法");
}
public static void main(String[] args) {
SpringApplication application= new SpringApplication(DemoApplication.class);
//application.addListeners(new ApplicationStartingEventistener());
application.run(args);
//ScheduledExecutorService timer = Executors.newScheduledThreadPool(2);
}
}
运行结果
2021-03-24 11:35:06.776 INFO 51476 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication using Java 1.8.0_181 on DESKTOP-J55VRAQ with PID 51476 (C:\Users\baicells\eclipse-workspace\demo\target\classes started by baicells in C:\Users\baicells\eclipse-workspace\demo)
2021-03-24 11:35:06.782 INFO 51476 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
我是初始化方法
2021-03-24 11:35:09.226 INFO 51476 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 4.286 seconds (JVM running for 6.326)
Disconnected from the target VM, address: '127.0.0.1:49953', transport: 'socket'
Process finished with exit code 0
2.2 方案二
pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
通过上诉我们可以看到我们引入了web项目
application.yaml文件
spring:
application:
name: demo
#非web的方式运行
main:
web-application-type: none
server:
port: 8080
实现SmartLifecycle完成任务
@Component
public class TestSmartLifecycle implements SmartLifecycle {
private boolean isRunning = false;
/**
* 1. 我们主要在该方法中启动任务或者其他异步服务,比如开启MQ接收消<br/>
* 2. 当上下文被刷新(所有对象已被实例化和初始化之后)时,将调用该方法,默认生命周期处理器将检查每个SmartLifecycle对象的isAutoStartup()方法返回的布尔值。
* 如果为“true”,则该方法会被调用,而不是等待显式调用自己的start()方法。
*/
@Override
public void start() {
System.out.println("start");
// 执行完其他业务后,可以修改 isRunning = true
isRunning = true;
}
/**
* 如果工程中有多个实现接口SmartLifecycle的类,则这些类的start的执行顺序按getPhase方法返回值从小到大执行。<br/>
* 例如:1比2先执行,-1比0先执行。 stop方法的执行顺序则相反,getPhase返回值较大类的stop方法先被调用,小的后被调用。
*/
@Override
public int getPhase() {
// 默认为0
return 0;
}
/**
* 根据该方法的返回值决定是否执行start方法。<br/>
* 返回true时start方法会被自动执行,返回false则不会。
*/
@Override
public boolean isAutoStartup() {
// 默认为false
return true;
}
/**
* 1. 只有该方法返回false时,start方法才会被执行。<br/>
* 2. 只有该方法返回true时,stop(Runnable callback)或stop()方法才会被执行。
*/
@Override
public boolean isRunning() {
// 默认返回false
return isRunning;
}
/**
* SmartLifecycle子类的才有的方法,当isRunning方法返回true时,该方法才会被调用。
*/
@Override
public void stop(Runnable callback) {
System.out.println("stop(Runnable)");
// 如果你让isRunning返回true,需要执行stop这个方法,那么就不要忘记调用callback.run()。
// 否则在你程序退出时,Spring的DefaultLifecycleProcessor会认为你这个TestSmartLifecycle没有stop完成,程序会一直卡着结束不了,等待一定时间(默认超时时间30秒)后才会自动结束。
// PS:如果你想修改这个默认超时时间,可以按下面思路做,当然下面代码是springmvc配置文件形式的参考,在SpringBoot中自然不是配置xml来完成,这里只是提供一种思路。
// <bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
// <!-- timeout value in milliseconds -->
// <property name="timeoutPerShutdownPhase" value="10000"/>
// </bean>
callback.run();
isRunning = false;
}
/**
* 接口Lifecycle的子类的方法,只有非SmartLifecycle的子类才会执行该方法。<br/>
* 1. 该方法只对直接实现接口Lifecycle的类才起作用,对实现SmartLifecycle接口的类无效。<br/>
* 2. 方法stop()和方法stop(Runnable callback)的区别只在于,后者是SmartLifecycle子类的专属。
*/
@Override
public void stop() {
System.out.println("stop");
isRunning = false;
}
运行结果
2021-03-24 11:36:30.257 INFO 49516 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication using Java 1.8.0_181 on DESKTOP-J55VRAQ with PID 49516 (C:\Users\baicells\eclipse-workspace\demo\target\classes started by baicells in C:\Users\baicells\eclipse-workspace\demo)
2021-03-24 11:36:30.266 INFO 49516 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
我是初始化方法
start
2021-03-24 11:36:32.355 INFO 49516 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 3.883 seconds (JVM running for 5.505)
stop(Runnable)
Disconnected from the target VM, address: '127.0.0.1:49993', transport: 'socket'
Process finished with exit code 0
结论 实现SmartLifecycle接口,会在容器加载完成后执行start方法,容器销毁前执行stop方法
2.3 方案三
pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
通过上诉我们可以看到我们没有引入了web项目
application.yaml文件
spring:
application:
name: demo
@PostConstruct完成任务
public class DemoApplicationCommandLineRunner implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DemoApplicationCommandLineRunner.class,args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("我是CommandLineRunner");
}
}
运行结果
2021-03-24 11:46:49.797 INFO 51928 --- [ main] c.e.d.DemoApplicationCommandLineRunner : Starting DemoApplicationCommandLineRunner using Java 1.8.0_181 on DESKTOP-J55VRAQ with PID 51928 (C:\Users\baicells\eclipse-workspace\demo\target\classes started by baicells in C:\Users\baicells\eclipse-workspace\demo)
2021-03-24 11:46:49.803 INFO 51928 --- [ main] c.e.d.DemoApplicationCommandLineRunner : No active profile set, falling back to default profiles: default
我是初始化方法
start
2021-03-24 11:46:51.429 INFO 51928 --- [ main] c.e.d.DemoApplicationCommandLineRunner : Started DemoApplicationCommandLineRunner in 2.819 seconds (JVM running for 4.259)
我是CommandLineRunner
stop(Runnable)
Process finished with exit code 0
2.4方案4
实现ApplicationListener监听
public class TestListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationStartingEvent) {
System.out.println("1111");
}
if (event instanceof ApplicationEnvironmentPreparedEvent){
System.out.println("环境初始化!!!");
} else if (event instanceof ApplicationPreparedEvent){
System.out.println("初始化完成!!!");
} else if (event instanceof ContextRefreshedEvent) {
System.out.println("应用刷新!!");
} else if (event instanceof ApplicationReadyEvent) {
System.out.println("项目启动完成!!");
} else if (event instanceof ContextStartedEvent) {
System.out.println("应用启动!!");
} else if (event instanceof ContextStoppedEvent) {
System.out.println("项目中止!!");
} else if (event instanceof ContextClosedEvent) {
System.out.println("应用关闭!!");
}
}
}
容器加入自定义监听
1:启动类中添加
SpringApplication application= new SpringApplication(DemoApplication.class);
application.addListeners(new TestListener());
2或者配置文件中制定:
#配置启动监听
context:
listener:
classes: com.example.demo.TestListener