springboot项目中Quartz

news2025/4/19 16:29:10

下面内容大家可在自己创建的 springboot项目中 玩

1 定时清理垃圾图片

定时任务组件Quartz,可以根据我们设定的周期,定时执行目标任务计划

1.1 Quartz介绍(了解)

Quartz是Job scheduling(作业调度)领域的一个开源项目,和spring完美整合。
Quartz既可以单独使用也可以跟spring框架整合使用,在实际开发中一般会使用后者。
使用Quartz可以开发一个或者多个定时任务,每个定时任务可以单独指定执行的时间,
例如每隔1小时执行一次、每个月第一天上午10点执行一次、每个月最后一天下午5点执行一次等。

官网:http://www.quartz-scheduler.org/

1.2 Quartz入门案例

基于Quartz和springboot整合的方式使用。

第一步:创建定时任务模块 : quartz-boot

导入Quartz坐标,在commons模块 导入,pom.xml文件如下

  		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

只需要在当前模块导入commons模块即可

第二步:编写quartz的任务执行对象

Springboot整合quartz 只需要通过 注解即可完成开发

- @Scheduled   任务调度执行  注解添加到目标对象的方法上即可  配置方法的执行周期

- @EnableScheduling  开启任务调度  在启动类上添加  

注意启动类的位置

注意:启动类要添加注解:@EnableScheduling // 开启任务调度

@Component //  定义任务实现类
public class AliyunOssScanClean {

    /**
     * 但是spring的@Scheduled只支持6位,年份是不支持的,带年份的7位格式会报错:
     * Cron expression must consist of 6 fields (found 7 in "1/5 * * * * ? 2018")
     *
     * 
     * @Scheduled 注解表示当前方法就是一个任务调度执行对象 
     * 通过cron表达式 来配置 该方法的执行周期
     * **/

    @Scheduled(cron = "*/5 * * * * ?") //  5秒 直接在方法上使用注解即可完成扫描
      public  void  run(){
          System.out.println("----执行扫描一次1---");
      }
      
      
      @Scheduled(cron = "*/3 * * * * ?") //  直接在方法上使用注解即可完成扫描
      public  void  run1(){
          System.out.println("----执行扫描一次2---");
      }
    
      
      @Scheduled(cron = "*/2 * * * * ?") //  直接在方法上使用注解即可完成扫描
    public  void  run2(){
        System.out.println("----执行扫描一次3---");
    }
    
}

执行启动类的main 注意启动类的位置 能够扫描到AliyunOssScanClean.java 任务实现类。

@SpringBootApplication
@EnableScheduling//  开启任务调度
public class Main {
    public static void main(String[] args) {

        SpringApplication.run(Main.class,args);
        System.out.println("-------任务调度开启了----------");

    }
}

我们发现quartz 可以定时执行对应的业务! 通过我们配置文件可以修改任务执行的周期!

1.3 cron表达式学习

上面的入门案例中我们指定了一个表达式:0/3 * * * * ?

这种表达式称为cron表达式,通过cron表达式可以灵活的定义出符合要求的程序执行的时间。

本小节我们就来学习一下cron表达式的使用方法。

Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

  (1) Seconds Minutes Hours DayofMonth Month DayofWeek Year

  (2)Seconds Minutes Hours DayofMonth Month DayofWeek

corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份

每个域都有自己允许的值和一些特殊字符构成,使用这些特殊字符可以使我们定义的表达式更加灵活。

下面是对这些特殊字符的介绍:

   (1)*:表示匹配该域的任意值。假如在Minutes域使用*, 即表示每分钟都会触发事件。

  (2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。

  (3)-:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次 

  (4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次. 

  (5),:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。 

  (6)L:表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。 

  (7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。

  (8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。 

  (9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。

corn表达式案例:

*/5 * * * * ? 每隔5秒执行一次
0 */1 * * * ? 每隔1分钟执行一次
0 0 5-15 * * ? 每天5-15点整点触发
0 0/3 * * * ? 每三分钟触发一次
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发 
0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发



0 0 12 ? * WED 表示每个星期三中午12点
0 0 17 ? * TUES,THUR,SAT 每周二、四、六下午五点
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发 
0 15 10 ? * MON-FRI 周一至周五的上午10:15触发



"30 10 * * * ?" 每小时的10分30秒触发任务
"30 10 1 * * ?" 每天1点10分30秒触发任务
"30 10 1 20 * ?" 每月20号1点10分30秒触发任务
"30 10 1 20 10 ? *" 每年10月20号1点10分30秒触发任务
"30 10 1 20 10 ? 2011" 2011年10月20号1点10分30秒触发任务
"30 10 1 ? 10 * 2011" 2011年10月每天1点10分30秒触发任务
"30 10 1 ? 10 SUN 2011" 2011年10月每周日1点10分30秒触发任务
"15,30,45 * * * * ?" 每15秒,30秒,45秒时触发任务


0 * * * * ? 每1分钟触发一次

0 0 * * * ? 每天每1小时触发一次

0 0 10 * * ? 每天10点触发一次

0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发

0 30 9 1 * ? 每月1号上午9点半

0 15 10 15 * ? 每月15日上午10:15触发

*/15 * * * * ? 每隔5秒执行一次

0 */1 * * * ? 每隔1分钟执行一次

0 0 5-15 * * ? 每天5-15点整点触发

0 0/3 * * * ? 每三分钟触发一次

0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发

0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发

0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发

0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时

0 0 10,14,16 * * ? 每天上午10点,下午2点,4点

0 0 12 ? * WED 表示每个星期三中午12点

0 0 17 ? * TUES,THUR,SAT 每周二、四、六下午五点

0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发

0 15 10 ? * MON-FRI 周一至周五的上午10:15触发

0 0 23 L * ? 每月最后一天23点执行一次

0 15 10 L * ? 每月最后一日的上午10:15触发

0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发

0 15 10 * * ? 2005 2005年的每天上午10:15触发

0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发

0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发

1.4 cron表达式在线生成器

前面介绍了cron表达式,但是自己编写表达式还是有一些困难的,我们可以借助一些cron表达式在线生成器来根据我们的需求生成表达式即可。

http://cron.qqe2.com/

1.5 xxl-job 分布式任务调度

XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

Quartz的不足

  • 问题一:调用API的的方式操作任务,不人性化;

  • 问题二:需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重。

  • 问题三:调度逻辑和QuartzJobBean耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多, 同时调度任务逻辑逐渐加重的情况加,此时调度系统的性能将大大受限于业务;

  • 问题四:quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,会导致节点负载悬殊非常大;而XXL-JOB通过执行器实现“协同分配式”运行任务,充分发挥集群优势,负载各节点均衡。

XXL-JOB弥补了quartz的上述不足之处。

2 Apache POI处理excel数据

POI介绍

Apache POI是用Java编写的免费开源的跨平台的Java API,Apache
POI提供API给Java程序对Microsoft
Office格式档案读和写的功能,其中使用最多的就是使用POI操作Excel文件。

POI常用对象说明:

HSSF - 提供读写Microsoft Excel XLS格式档案的功能  
XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能  
HWPF - 提供读写Microsoft Word DOC格式档案的功能  
HSLF - 提供读写Microsoft PowerPoint格式档案的功能  
HDGF - 提供读Microsoft Visio格式档案的功能  
HPBF - 提供读Microsoft Publisher格式档案的功能  
HSMF - 提供读Microsoft Outlook格式档案的功能

2.1 快速入门案例

目标: 从Excel文件读取数据,hello.xlsx见资料:

内容如下:

第一步:导入poi依赖

maven坐标:项目中以及无需重复导入,但是自己测试需要导入。

<dependency>  
 <groupId>org.apache.poi</groupId>  
 <artifactId>poi</artifactId>   
    <version>3.14</version>   
</dependency>  
<dependency>  
 <groupId>org.apache.poi</groupId>  
 <artifactId>poi-ooxml</artifactId>  
 <version>3.14</version>      
</dependency>
第二步:自己创建测试用例

读取excel数据

方式一

使POI可以从一个已经存在的Excel文件中读取数据

注意 读取excel文件 api编写规则顺序:工作簿-----工作区-----记录行 -----单元格

POI操作Excel表格封装了几个核心对象:

**XSSFWorkbook:工作簿

XSSFSheet:工作表

Row:行

Cell:单元格**

public class PoiTest {  
    @Test  
    public void demo1() throws IOException {  
        //创建工作簿  
        XSSFWorkbook workbook = new XSSFWorkbook("D:\\hello.xlsx");  
        //获取工作表,既可以根据工作表的顺序获取,也可以根据工作表的名称获取  
        XSSFSheet sheet = workbook.getSheetAt(0);  
        //遍历工作表获得行对象  
        for (Row row : sheet) {  
        //遍历行对象获取单元格对象  
            for (Cell cell : row) {  
            //获得单元格中的值  
            String value = cell.getStringCellValue();  
            System.out.println(value);  
     	}  
    }  
      workbook.close();  
    }  
}

方式二

上面案例是通过遍历工作表获得行,遍历行获得单元格,最终获取单元格中的值。

还有一种方式就是获取工作表最后一个行号,从而根据行号获得行对象,通过行获取最后一个单元格索引,从而根据单元格索引获取每行的一个单元格对象。

代码如下:

@Test  
public void demo2() throws IOException {  
    //创建工作簿  
    XSSFWorkbook workbook = new XSSFWorkbook("D:\\hello.xlsx");  
    //获取工作表,既可以根据工作表的顺序获取,也可以根据工作表的名称获取  
    XSSFSheet sheet = workbook.getSheetAt(0);  
    //获取当前工作表最后一行的行号,行号从0开始  
    int lastRowNum = sheet.getLastRowNum();  
    for(int i=0;i<=lastRowNum;i++){  
    //根据行号获取行对象  
    XSSFRow row = sheet.getRow(i);  
    //获取当前行的最后一个单元格的索引号  
    short lastCellNum = row.getLastCellNum(); 
        // row.getCell(索引) 获取指定单元格
    //遍历每一行上的每一个单元格  
        for(short j=0;j<lastCellNum;j++){  
            String value = row.getCell(j).getStringCellValue();  
            System.out.println(value);  
           }  
         }  
     workbook.close();  
}
第三步:poi向excel写入数据

使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘

@Test  
public void demo3() throws IOException {  
//在内存中创建一个Excel文件  
XSSFWorkbook workbook = new XSSFWorkbook();  
//创建工作表,指定工作表名称  
XSSFSheet sheet = workbook.createSheet("传智播客");  

//创建行,0表示第一行  
XSSFRow row = sheet.createRow(0);  
//创建单元格,0表示第一个单元格  
row.createCell(0).setCellValue("编号");  
row.createCell(1).setCellValue("名称");  
row.createCell(2).setCellValue("年龄");  

XSSFRow row1 = sheet.createRow(1);  
row1.createCell(0).setCellValue("1");  
row1.createCell(1).setCellValue("小明");  
row1.createCell(2).setCellValue("10");  

XSSFRow row2 = sheet.createRow(2);  
row2.createCell(0).setCellValue("2");  
row2.createCell(1).setCellValue("小王");  
row2.createCell(2).setCellValue("20");  

//通过输出流将workbook对象输出到磁盘  
FileOutputStream out = new FileOutputStream("D:\\itcast.xlsx");  
workbook.write(out);  
out.flush();//清空缓冲区  
out.close();  
workbook.close();  

}

经常操作excel文件,我们可以将excel的crud封装一个通用工具类

特殊的方法,可自己研究

  double numberValue =  row.getCell(1).getNumericCellValue();     //如果单元格没有数据,则getNumericCellValue返回0
  Date date= row.getCell(0).getDateCellValue(); //如果单元格没有数据,则getDateCellValue返回null

XSSFWorkbook workbook = new XSSFWorkbook(还可以是上传文件的输入流);  


 multipartFile.getOriginalFilename();上传文件原始名
 multipartFile.getInputStream();上传文件输入流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/397221.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

树莓派3B搭建HomeAssistant,alist,cpolar,plex,transmission

一、手把手教学树莓派搭建homeassistant环境&#xff1a;内存卡16G&#xff0c;树莓派3B&#xff0c;官方工具烧写镜像&#xff0c;我烧的是树莓派系统&#xff0c;设置里面填写用户名密码&#xff0c;WiFi和密码&#xff0c;同时打开SSH服务。安装docker树莓派使用ssh连接了 先…

C++基础了解-05-C++常量

C常量 一、C常量 常量是固定值&#xff0c;在程序执行期间不会改变。这些固定的值&#xff0c;又叫做字面量。 常量可以是任何的基本数据类型&#xff0c;可分为整型数字、浮点数字、字符、字符串和布尔值。 常量就像是常规的变量&#xff0c;只不过常量的值在定义后不能进…

uni-app框架基础知识

uni-app框架基础知识 uniapp就是vue开发&#xff0c;可以使用vue2和vue3的语法&#xff0c;另外编译和运行都最好在HBuilderX中进行生命周期可以使用vue或者小程序的生命周期不同&#xff1a; 最好不要使用vue的路由&#xff0c;直接使用uniapp的路由&#xff08;它和小程序一…

项目实战典型案例8——让软件的使用者成为软件的设计者

让软件的使用者成为软件的设计者一&#xff1a;背景介绍二&#xff1a;思路&方案公司的产品设计理念如果你设计的软件猪不能使&#xff0c;你就是猪让每一个软件的使用者都成为我们软件的设计者过程四&#xff1a;总结五&#xff1a;升华一&#xff1a;背景介绍 由于同时对…

2020蓝桥杯真题反倍数 C语言/C++

题目描述 给定三个整数 a,b,c&#xff0c;如果一个整数既不是 a 的整数倍也不是 b 的整数倍还不是 c 的整数倍&#xff0c;则这个数称为反倍数。 请问在 1 至 n 中有多少个反倍数。 输入描述 输入的第一行包含一个整数 n。 第二行包含三个整数a,b,c&#xff0c;相邻两个数之…

Stimulsoft Dashboards.WEB 23.1.8 完美Patch

Stimulsoft Dashboards.WEB 在 Web 应用程序中创建仪表板 Stimulsoft Dashboards.WEB 是一种工具&#xff0c;用于在 ASP.NET、.NET Core、ASP.NET MVC 和 Blazor 平台上开发的 Web 应用程序中创建、编辑、导出和查看仪表板。该产品包括各种数据分析和可视化元素&#xff0c;可…

花括号展开II[栈模拟dfs]

栈模拟dfs前言一、花括号展开II二、栈模拟dfs总结参考资料前言 递归调用&#xff0c;代码非常的简洁。但是可以通过显式栈来模拟栈中的内容&#xff0c;锻炼自己的代码能力&#xff0c;清楚知道栈帧中需要的内容。 一、花括号展开II 二、栈模拟dfs 每碰到一个左括号&#xf…

sheng的学习笔记-服务熔断与降级组件Hystrix

在微服务架构中&#xff0c;一个应用往往由多个服务组成&#xff0c;这些服务之间相互依赖&#xff0c;依赖关系错综复杂。例如一个微服务系统中存在 A、B、C、D、E、F 等多个服务&#xff0c;它们的依赖关系如下图。图1&#xff1a;服务依赖关系通常情况下&#xff0c;一个用户…

基于安森美深力科电子一款能实现大功率DC/DC电源转换 NCP13992ACDR2G 全桥LLC方案

基于安森美深力科电子一款能实现大功率DC/DC电源转换 NCP13992ACDR2G 全桥LLC方案 什么是LLC:LLC电路是由2个电感和1个电容构成的谐振电路&#xff0c;故称之为LLC&#xff0c;由于能实现软开关&#xff0c;有效地减小开关损耗和容许高频运行&#xff0c;所以在高频功率变换领…

网关(Gateway)

本文内容网关&#xff0c;网关作用&#xff0c;默认网关&#xff0c;网关和路由器区别网关协议&#xff0c;网关分类NAT网关一、概述网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连&#xff0c;是最复杂的网络互连设备&#xff0c;仅用于两个高层协议…

计算机网络-- 应用层(day08)

计算机网络两种方式 网络应用程序运行再处于网络边缘的不同端系统上&#xff0c;通过彼此间的通信来共同完成某项任务。 开发一种新的网络应用首先要考虑的问题就是网络应用程序在各种端系统上的组织方式和它们之间的关系。 目前流行的主要有以下两种&#xff1a; 客户/服务器…

libevent 学习笔记

一、参考 libevent Libevent深入浅出 - 《Libevent 深入浅出》 - 书栈网 BookStack libevent 之 event config的相关函数介绍_event_config_new_yldfree的博客-CSDN博客 Libevent之evbuffer详解_有时需要偏执狂的博客-CSDN博客 二、libevent概述 libevent 就是将网络、I…

数组中的逆序对

解题思路1&#xff1a; 看到这个题目&#xff0c;我们的第一反应是顺序扫描整个数组。每扫描到一个数组的时候&#xff0c;逐个比较该数字和它后面的数字的大小。如果后面的数字比它小&#xff0c;则这两个数字就组成了一个逆序对。假设数组中含有n个数字。由于每个数字都要和…

JavaScript的学习

一、引言 1.1 JavaScript简介 JavaScript一种解释性脚本语言&#xff0c;是一种动态类型、弱类型、基于原型继承的语言&#xff0c;内置支持类型。它的解释器被称为JavaScript引擎&#xff0c;作为浏览器的一部分&#xff0c;广泛用于客户端的脚本语言&#xff0c;用来给HTML网…

信息系统基本知识(六)

大纲 信息系统与信息化信息系统开发方法常规信息系统集成技术软件工程新一代信息技术信息系统安全技术信息化发展与应用信息系统服务管理信息系统服务规划企业首席信息管及其责任 1.7 信息化发展与应用 我国在“十三五”规划纲要中&#xff0c;将培育人工智能、移动智能终端…

推荐系统[九]项目技术细节讲解z2:搜索Query理解[Term Weight、Query 改写、同义词扩写]和语义召回技术

搜索Query理解和语义召回技术 随着用户规模和产品的发展, 搜索面临着越来越大的 query 长尾化挑战,query 理解是提升搜索召回质量的关键。本次将介绍搜索在 query term weighting,同义词扩展,query 改写,以及语义召回等方向上的实践方法和落地情况。 1.面临问题:长尾 qu…

h264编码概述八(哥伦布编码ue(v))

一、概述 熵编码是无损编码的一种方法。该编码方法的宗旨是找到一种编码&#xff0c;使得码字的平均码长达到熵极限。具体实施是&#xff0c;对出现概率较大的符号&#xff0c;取较短的码长&#xff0c;对出现概率较小的符号取较大的码长。 H.264中使用的熵编码有&#xff1a;…

【面试1v1实景模拟】面试中常见的Java关键字详解

笑小枫专属目录老面&#x1f474;&#xff1a;Java中有哪些关键字老面&#x1f474;&#xff1a;简单介绍一下 final 关键字老面&#x1f474;&#xff1a;简单介绍一下 this、super 关键字老面&#x1f474;&#xff1a;简单介绍一下 static 关键字老面&#x1f474;&#xff…

深度解析Spring Boot自动装配原理

废话不多说了&#xff0c;直接来看源码。源码解析SpringBootApplication我们在使用idea创建好Spring Boot项目时&#xff0c;会发现在启动类上添加了SpringBootApplication注解&#xff0c;这个注解就是Spring Boot的核心所在。点击注解可以查看到到它的实现ementType.TYPE) Re…

JavaScript简单记录

简介 JavaScript 诞生于 1995 年。JavaScript 使得现代网页应用程序成为可能,使用 JavaScript 可以直接与用户交互&#xff0c;从而避免每一个动作都需要重新载入页 面。但有许多传统网站也会使用 JavaScript 来提供实时交互以及更加智能的表单功能。 JavaScript 其实和名为Ja…