spring-boot 如何实现单次执行程序
spring-boot 单次执行程序
spring-boot做为spring的集大成框架,大部分时候作为WEB服务被集成使用,但某些情况下,需要手动执行一些逻辑的情况下,单次运行的类似脚本的程序也是很有用的。
本文记录一下使用spring-boot作为单次可执行程序配置方式。
pom.xml
注意:pom.xml部分只需引入spring-boot-starter模块,尤其不要引入web模块,其他非spring本身模块可以随意引入
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- 按工程习惯处理parent部分 -->
</parent>
<groupId>com.leon</groupId>
<artifactId>sprint-boot-task</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
主要代码结构
Service类
@Service
public class StatService {
public void doSomething() {
System.out.println("===================: this is a test service but nothing");
}
}
执行逻辑入口类
@Component
public class StatTask {
private StatService statService;
@Autowired
public StatTask(StatService statService) {
this.statService = statService;
}
public void doSomething() {
statService.doSomething();
}
}
Spring-boot 启动类
@SpringBootApplication
public class TaskApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TaskApplication.class, args);
StatTask statTask = context.getBean(StatTask.class); // 获取逻辑入口类的实例
statTask.doSomething();
}
}
如此这般后,启动这个springboot工程,执行完启动类中的调用过程后,程序就会自动退出。
基本上,不配置启用spring mvc和定时Job,这种配置下的springboot就是一个“脚本”程序。
这里举个?,上面的代码加上两个注解,就会变成常驻进程程序:
执行逻辑入口类
@Component
public class StatTask {
private StatService statService;
@Autowired
public StatTask(StatService statService) {
this.statService = statService;
}
@Scheduled(fixedRate = 5000L) // --------------这里-----------------
public void doSomething() {
statService.doSomething();
}
}
Spring-boot 启动类
@SpringBootApplication
@EnableScheduling // --------------这里---------------
public class TaskApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TaskApplication.class, args);
StatTask statTask = context.getBean(StatTask.class);
statTask.doSomething();
}
}
与最上面区别的是,上面只执行一次,输出 “this is a test service but nothing” 就完事了,进程自动退出,
加上两个注解后就会每5秒输出一次 “this is a test service but nothing”,且进程永驻。
当然这种情况下使用脚本语言如python、nodeJs等可能更好一些,但在其他语言不熟的情况下,使用spring-boot来应急也是极好的。
启动时执行单次任务
最近做任务遇到一个问题,需要在项目启动时候执行扫描数据库表的任务,用于异常恢复容灾,一开始想的是可不可以使用定时任务
代码如下 并且在启动类加上
@EnableScheduling注解就可以实现定时去执行任务了
package com.beihui.service.task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class XXXTask {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Scheduled(cron = "0 0 0 * * ?")
public void bTask() {
long startCurrentTime = System.currentTimeMillis();
logger.info("开始执行定时任务:" + startCurrentTime);
//业务处理
long endTime = System.currentTimeMillis();
logger.info("定时任务:执行结束,花费时间" + (endTime - startCurrentTime));
}
@Scheduled(cron = "0 */1 * * * ?")
public void runUpdateDbTask() {
long startCurrentTime = System.currentTimeMillis();
logger.info("开始执行更新数据库剩余次数定时任务:" + startCurrentTime);
//业务处理
long endTime = System.currentTimeMillis();
logger.info("定时任务:执行结束,花费时间" + (endTime - startCurrentTime));
}
@Scheduled(fixedDelay = 60 * 1000 * 10)
public void cTask() {
long startCurrentTime = System.currentTimeMillis();
//业务处理
long endTime = System.currentTimeMillis();
logger.info("定时任务:执行结束,花费时间" + (endTime - startCurrentTime));
}
}
但是这个并不能单次执行任务,所以后来 使用listener
代码如下,并在启动类加上
@ServletComponentScan注解
package xx.xx.xx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class XXXListener implements ServletContextListener {
private Logger logger = LoggerFactory.getLogger(this.getClass());
//项目启动执行
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
long startTime = System.currentTimeMillis();
logger.info("开始执行启动任务,{}"+startTime);
//业务处理
long endTime = System.currentTimeMillis();
logger.info("执行启动任务结束,共花费时间{}"+(startTime-endTime));
}
//项目终止时执行
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341