下面内容大家可在自己创建的 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文件如下
org.springframework.bootspring-boot-starter-quartz
只需要在当前模块导入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秒 直接在方法上使用注解即可完成扫描publicvoidrun(){System.out.println("----执行扫描一次1---");}@Scheduled(cron = "*/3 * * * * ?") //直接在方法上使用注解即可完成扫描publicvoidrun1(){System.out.println("----执行扫描一次2---");}@Scheduled(cron = "*/2 * * * * ?") //直接在方法上使用注解即可完成扫描publicvoidrun2(){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)" />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,ApachePOI提供API给Java程序对MicrosoftOffice格式档案读和写的功能,其中使用最多的就是使用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坐标:项目中以及无需重复导入,但是自己测试需要导入。
org.apache.poi poi 3.14 org.apache.poi poi-ooxml 3.14
第二步:自己创建测试用例
读取excel数据
方式一
使POI可以从一个已经存在的Excel文件中读取数据
注意 读取excel文件 api编写规则顺序:工作簿-----工作区-----记录行 -----单元格
POI操作Excel表格封装了几个核心对象:
**XSSFWorkbook:工作簿
XSSFSheet:工作表
Row:行
Cell:单元格**
public class PoiTest {@Testpublic 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();}}
方式二
上面案例是通过遍历工作表获得行,遍历行获得单元格,最终获取单元格中的值。
还有一种方式就是获取工作表最后一个行号,从而根据行号获得行对象,通过行获取最后一个单元格索引,从而根据单元格索引获取每行的一个单元格对象。
代码如下:
@Testpublic 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文件下载到磁盘
@Testpublic 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返回0Date date= row.getCell(0).getDateCellValue(); //如果单元格没有数据,则getDateCellValue返回nullXSSFWorkbook workbook = new XSSFWorkbook(还可以是上传文件的输入流); multipartFile.getOriginalFilename();上传文件原始名 multipartFile.getInputStream();上传文件输入流