springboot搭建非web项目

4,747 阅读5分钟

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