1.Quartz的介绍
Quartz是Job scheduling(作业调度)领域的一个开源项目,Quartz既可以单独使用也可以跟spring框架整合使用,在实际开发中一般会使用后者。使用Quartz可以开发一个或者多个定时任务,每个定时任务可以单独指定执行的时间,例如每隔1小时执行一次、每个月第一天上午10点执行一次、每个月最后一天下午5点执行一次等。
官网:http://www.quartz-scheduler.org/
2.Quartz的使用步骤
1.创建子模块 health-jobs
webapp骨架
2.修改pom.xml文件
引入需要的三方库
3.自定义一个任务类
调用任务类,普通类普通方法
4.增加spring-jobs.xml文件
配置任务对象、调度对象,调度工厂
5.修改web.xml文件
容器启动,加载spring配置文件
3.Quartz的使用演示
本案例基于Quartz和spring整合的方式使用。具体步骤:
(1)创建maven子模块工程health-jobs,骨架webapp
(2)修改pom.xml文件
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <parent>
6 <artifactId>itcast_health</artifactId>
7 <groupId>com.itheima.health</groupId>
8 <version>1.0-SNAPSHOT</version>
9 </parent>
10 <modelVersion>4.0.0</modelVersion>
11
12 <artifactId>health-jobs</artifactId>
13 <packaging>war</packaging>
14
15 <name>health-jobs</name>
16
17 <properties>
18 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19 <maven.compiler.source>1.7</maven.compiler.source>
20 <maven.compiler.target>1.7</maven.compiler.target>
21 </properties>
22 <dependencies>
23
24 <dependency>
25 <groupId>com.itheima.health</groupId>
26 <artifactId>health_common</artifactId>
27 <version>1.0-SNAPSHOT</version>
28 </dependency>
29 <dependency>
30 <groupId>org.springframework</groupId>
31 <artifactId>spring-webmvc</artifactId>
32 </dependency>
33 <dependency>
34 <groupId>org.springframework</groupId>
35 <artifactId>spring-tx</artifactId>
36 </dependency>
37 <dependency>
38 <groupId>org.quartz-scheduler</groupId>
39 <artifactId>quartz</artifactId>
40 </dependency>
41 <dependency>
42 <groupId>org.quartz-scheduler</groupId>
43 <artifactId>quartz-jobs</artifactId>
44 </dependency>
45 <dependency>
46 <groupId>redis.clients</groupId>
47 <artifactId>jedis</artifactId>
48 </dependency>
49 <dependency>
50 <groupId>org.springframework</groupId>
51 <artifactId>spring-context-support</artifactId>
52 </dependency>
53 <dependency>
54 <groupId>com.qiniu</groupId>
55 <artifactId>qiniu-java-sdk</artifactId>
56 </dependency>
57 </dependencies>
58 <build>
59 <finalName>health-jobs</finalName>
60 <plugins>
61 <plugin>
62 <groupId>org.apache.tomcat.maven</groupId>
63 <artifactId>tomcat7-maven-plugin</artifactId>
64 <configuration>
65 <path>/</path>
66 <port>9003</port>
67 </configuration>
68 </plugin>
69 </plugins>
70 </build>
71 </project>
(3)自定义一个Job(将来做事的地方,要执行的任务放在这里就行)
main下创建java目录 (刷新maven工程),然后创建com.itheima.health.jobs包,然后新建一个任务调度类ClearImageJob,任务内容暂时做普通打印即可。
/**
* 定时任务:在这里定义你想要完成的功能
*public class ClearImageJob {
/**
* 定义清理图片的任务
*/
public void clearImageJob(){
System.out.println("clearImageJob......");
}
}
(4)创建配置文件spring-jobs.xml,配置自定义Job、任务描述、触发器、调度工厂等
- 自动扫包
- 注册任务对象
- 注册JobDetail
- 定义触发器
- 定义调度工厂
在main下创建resources目录,刷新maven后,在目录下创建spring-jobs.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans.xsd
7 http://www.springframework.org/schema/context
8 http://www.springframework.org/schema/context/spring-context.xsd">
9
10 <!--自动扫包,后续注入jedis到任务调度类-->
11 <context:component-scan base-package="com.itheima.health"/>
12 <!--注册一个定义任务对象-->
13 <bean id = "clearImgJob" class="com.itheima.health.jobs.ClearImageJob"/>
14 <!-- 注册JobDetail,作用是负责通过反射调用指定的Job -->
15 <bean id="clearImgJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
16 <!--注入对象-->
17 <property name="targetObject" ref="clearImgJob"/>
18 <!--注入方法-->
19 <property name="targetMethod" value="clearImageJob"/>
20 </bean>
21 <!--注册一个触发器,指定任务触发的时间(间隔)-->
22 <bean id="jobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
23 <property name="jobDetail" ref="clearImgJobDetail"/>
24 <property name="cronExpression">
25 <!-- 每隔10秒执行一次任务 0/10 * * * * ? -->
26 <!-- 每隔2分钟执行一次任务 0 0/2 * * * ? -->
27 <!-- 每天凌晨2点执行一次任务 0 0 2 * * ? -->
28 <value>0/10 * * * * ?</value>
29 </property>
30 </bean>
31 <!--注册一个统一调用工厂,通过这个调度工厂调度任务-->
32 <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
33 <property name="triggers">
34 <list>
35 <ref bean="jobTrigger"/>
36 </list>
37 </property>
38 </bean>
39 </beans>
(5)修改web.xml,容器启动时,加载spring配置文件
1 <!DOCTYPE web-app PUBLIC
2 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
3 "http://java.sun.com/dtd/web-app_2_3.dtd" >
4
5 <web-app>
6 <display-name> Jobs Web Application</display-name>
7 <context-param>
8 <param-name>contextConfigLocation</param-name>
9 <param-value>classpath:spring-*.xml</param-value>
10 </context-param>
11 <listener>
12 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
13 </listener>
14 </web-app>
执行上面main方法观察控制台,可以发现每隔10秒会输出一次,说明每隔10秒自定义Job被调用一次。
(6) cron表达式在线生成器(http://www.bejson.com/othertools/cron/)
上面的入门案例中我们指定了一个表达式:0/10 * * * * ?
这种表达式称为cron表达式,通过cron表达式可以灵活的定义出符合要求的程序执行的时间。
4.定时清理垃圾图片
我们在文件上传成功后将图片保存到了一个redis集合中,当套餐数据插入到数据库后我们又将图片名称保存到了另一个redis集合中,通过计算这两个集合的差值就可以 获得所有垃圾图片的名称。本节基于Quartz定时任务,通过计算redis两个集合的差值找出所有的垃圾图片,就可以将垃圾图片清理掉。
实现流程:
1.增加spring-redis.xml
需要进行差值计算
2.修订spring-jobs.xml
修改为每天凌晨2点执行任务
3.增加七牛工具类
增加删除方法
4.修订定时任务类
进行差值计算,对差值结果就是需要清理的图片
操作步骤:
(1) 配置spring-redis.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
6 <property name="maxTotal">
7 <value>200</value>
8 </property>
9 <property name="minIdle">
10 <value>50</value>
11 </property>
12 <property name="testOnBorrow" value="true"/>
13 <property name="testOnReturn" value="true"/>
14 </bean>
15 <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
16 <constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
17 <constructor-arg name="host" value="127.0.0.1"/>
18 <constructor-arg name="port" value="6379"/>
19 </bean>
20 </beans>
(2) 修改spring-jobs.xml,调度时间改为每天凌晨2点执行
0 0 2 * * ?
1 <!--注册一个触发器,指定任务触发的时间(间隔)-->
2 <bean id="jobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
3 <property name="jobDetail" ref="clearImgJobDetail"/>
4 <property name="cronExpression">
5 <!--每隔10秒执行一次任务 0/10 **** ?-->
6 <!--每隔2分钟执行一次任务 0 0/2 *** ?-->
7 <!--每天凌晨2点执行一次任务 0 0 2 ** ?-->
8 <value>0 0 2 * * ?</value>
9 </property>
10 </bean>
(3)增加七牛工具类,删除不用的文件
1 /**
2 * 七牛云工具类
3 */
4 public class QiniuUtils {
5 public static String accessKey = "fhuiPBXFTZIgJdtZGuMtCUJ3zSrT7k3AHmVNE4UA";
6 public static String secretKey = "zKKxCW_HjQmwtl4JI80nMT0Ve2V7VZDbqT4zt_tT";
7 public static String bucket = "itcast_health";
8
9 /**
10 * 删除文件
11 * @param fileName 服务端文件名
12 */
13 public static void deleteFileFromQiniu(String fileName){
14 //构造一个带指定Zone对象的配置类
15 Configuration cfg = new Configuration(Zone.zone0());
16 String key = fileName;
17 Auth auth = Auth.create(accessKey, secretKey);
18 BucketManager bucketManager = new BucketManager(auth, cfg);
19 try {
20 bucketManager.delete(bucket, key);
21 } catch (QiniuException ex) {
22 //如果遇到异常,说明删除失败
23 System.err.println(ex.code());
24 System.err.println(ex.response.toString());
25 }
26 }
27 // 测试上传与删除
28 public static void main(String args[]) throws Exception{
29 // 测试删除
30 //deleteFileFromQiniu("f5eee75c0c5d4eeda1c5c49bee766603");
31 }
32 }
(4)修订ClearJob定时任务类
1 /**
2 * 定时任务:清理垃圾图片
3 */
4 public class ClearJob {
5 @Autowired//idea自动识别,xml文件顶部出现的context中勾选全部xml文件,就能正常识别了
6 private JedisPool jedisPool;
7 //清理图片
8 public void clearImageJob(){
9 //计算redis中两个集合的差值,获取垃圾图片名称
10 Set<String> set = jedisPool.getResource()
11 .sdiff(RedisConst.SETMEAL_PIC_RESOURCES,
12 RedisConst.SETMEAL_PIC_DB_RESOURCES);
13 Iterator<String> iterator = set.iterator();
14 while(iterator.hasNext()){
15 String pic = iterator.next();
16 //删除图片服务器中的图片文件
17 QiniuUtils.deleteFileFromQiniu(pic);
18 //删除redis中的数据
19 jedisPool.getResource().srem(RedisConst.SETMEAL_PIC_RESOURCES,pic);
20 }
21 }
22 }