spring-boot 如何實(shí)現(xiàn)單次執(zhí)行程序
spring-boot 單次執(zhí)行程序
spring-boot做為spring的集大成框架,大部分時(shí)候作為WEB服務(wù)被集成使用,但某些情況下,需要手動(dòng)執(zhí)行一些邏輯的情況下,單次運(yùn)行的類(lèi)似腳本的程序也是很有用的。
本文記錄一下使用spring-boot作為單次可執(zhí)行程序配置方式。
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> <!-- 按工程習(xí)慣處理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>
主要代碼結(jié)構(gòu)
Service類(lèi)
@Service public class StatService { public void doSomething() { System.out.println("===================: this is a test service but nothing"); } }
執(zhí)行邏輯入口類(lèi)
@Component public class StatTask { private StatService statService; @Autowired public StatTask(StatService statService) { this.statService = statService; } public void doSomething() { statService.doSomething(); } }
Spring-boot 啟動(dòng)類(lèi)
@SpringBootApplication public class TaskApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(TaskApplication.class, args); StatTask statTask = context.getBean(StatTask.class); // 獲取邏輯入口類(lèi)的實(shí)例 statTask.doSomething(); } }
如此這般后,啟動(dòng)這個(gè)springboot工程,執(zhí)行完啟動(dòng)類(lèi)中的調(diào)用過(guò)程后,程序就會(huì)自動(dòng)退出。
基本上,不配置啟用spring mvc和定時(shí)Job,這種配置下的springboot就是一個(gè)“腳本”程序。
這里舉個(gè)?,上面的代碼加上兩個(gè)注解,就會(huì)變成常駐進(jìn)程程序:
執(zhí)行邏輯入口類(lèi)
@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 啟動(dòng)類(lèi)
@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(); } }
與最上面區(qū)別的是,上面只執(zhí)行一次,輸出 “this is a test service but nothing” 就完事了,進(jìn)程自動(dòng)退出,
加上兩個(gè)注解后就會(huì)每5秒輸出一次 “this is a test service but nothing”,且進(jìn)程永駐。
當(dāng)然這種情況下使用腳本語(yǔ)言如python、nodeJs等可能更好一些,但在其他語(yǔ)言不熟的情況下,使用spring-boot來(lái)應(yīng)急也是極好的。
啟動(dòng)時(shí)執(zhí)行單次任務(wù)
最近做任務(wù)遇到一個(gè)問(wèn)題,需要在項(xiàng)目啟動(dòng)時(shí)候執(zhí)行掃描數(shù)據(jù)庫(kù)表的任務(wù),用于異常恢復(fù)容災(zāi),一開(kāi)始想的是可不可以使用定時(shí)任務(wù)
代碼如下 并且在啟動(dòng)類(lèi)加上
@EnableScheduling注解就可以實(shí)現(xiàn)定時(shí)去執(zhí)行任務(wù)了
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("開(kāi)始執(zhí)行定時(shí)任務(wù):" + startCurrentTime); //業(yè)務(wù)處理 long endTime = System.currentTimeMillis(); logger.info("定時(shí)任務(wù):執(zhí)行結(jié)束,花費(fèi)時(shí)間" + (endTime - startCurrentTime)); } @Scheduled(cron = "0 */1 * * * ?") public void runUpdateDbTask() { long startCurrentTime = System.currentTimeMillis(); logger.info("開(kāi)始執(zhí)行更新數(shù)據(jù)庫(kù)剩余次數(shù)定時(shí)任務(wù):" + startCurrentTime); //業(yè)務(wù)處理 long endTime = System.currentTimeMillis(); logger.info("定時(shí)任務(wù):執(zhí)行結(jié)束,花費(fèi)時(shí)間" + (endTime - startCurrentTime)); } @Scheduled(fixedDelay = 60 * 1000 * 10) public void cTask() { long startCurrentTime = System.currentTimeMillis(); //業(yè)務(wù)處理 long endTime = System.currentTimeMillis(); logger.info("定時(shí)任務(wù):執(zhí)行結(jié)束,花費(fèi)時(shí)間" + (endTime - startCurrentTime)); } }
但是這個(gè)并不能單次執(zhí)行任務(wù),所以后來(lái) 使用listener
代碼如下,并在啟動(dòng)類(lèi)加上
@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()); //項(xiàng)目啟動(dòng)執(zhí)行 @Override public void contextInitialized(ServletContextEvent servletContextEvent) { long startTime = System.currentTimeMillis(); logger.info("開(kāi)始執(zhí)行啟動(dòng)任務(wù),{}"+startTime); //業(yè)務(wù)處理 long endTime = System.currentTimeMillis(); logger.info("執(zhí)行啟動(dòng)任務(wù)結(jié)束,共花費(fèi)時(shí)間{}"+(startTime-endTime)); } //項(xiàng)目終止時(shí)執(zhí)行 @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件 FTP上傳下載隊(duì)列窗口實(shí)現(xiàn)(7)
這篇文章主要為大家詳細(xì)介紹了Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件,F(xiàn)TP上傳下載隊(duì)列窗口的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04IDEA報(bào)錯(cuò)Error?running‘Application‘:Command?line?is?too?lo
這篇文章主要介紹了IDEA報(bào)錯(cuò)Error?running?‘Application‘:Command?line?is?too?long的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06劍指Offer之Java算法習(xí)題精講排列與N叉樹(shù)
跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過(guò)之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03關(guān)于SSM框架下各層的解釋說(shuō)明(Controller等)
這篇文章主要介紹了關(guān)于SSM框架下各層的解釋說(shuō)明(Controller等),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02JavaSE實(shí)現(xiàn)圖書(shū)管理系統(tǒng)的示例代碼
這篇博客是在學(xué)習(xí)了一部分Java基礎(chǔ)語(yǔ)法之后的練習(xí)項(xiàng)目,通過(guò)這個(gè)小項(xiàng)目的練習(xí),對(duì)Java中的類(lèi)和對(duì)象,抽象類(lèi)和接口等進(jìn)行熟悉理解??旄S小編一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08springboot中@ConfigurationProperties無(wú)效果的解決方法
本文主要介紹了springboot中@ConfigurationProperties無(wú)效果,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06