简单的定时任务功能可以通过原生的java.util.Timer定义执行时间规则、继承java.util.TimeTask来定义执行逻辑来实现,更方便的是利用开源的quartz框架,只需定义几个spring配置文件的bean,建一个定时任务执行逻辑类即可。这里通过一个maven项目实例介绍第二种方式:
1、引入quartz、spring的jar包,看完整pom.xml
<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> <groupId>com.inspur.chinanet</groupId> <artifactId>point-circle</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>point-circle</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.12.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>com.vividsolutions</groupId> <artifactId>jts</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc14</artifactId> <version>10.2.0.2.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.inspur.chinanet.point.App</mainClass> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.tooling</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
2、定义spring配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <bean id="PropertyConfig" class="com.inspur.chinanet.point.util.PropertiesConfigUtil"> <property name="locations"> <list> <value>classpath:global.properties</value> </list> </property> <property name="fileEncoding"> <value>UTF-8</value> </property> <property name="ignoreResourceNotFound" value="true" /> <property name="ignoreUnresolvablePlaceholders" value="true" /> </bean> <bean id="jdbcImpl" class="com.inspur.chinanet.point.dao.JdbcImpl" /> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${driver.class}" /> <property name="url" value="${driver.url}" /> <property name="username" value="${db.username}" /> <property name="password" value="${db.password}" /> </bean> <!-- 使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job接口,通过targetMethod指定调用方法 --> <bean id="taskJob" class="com.inspur.chinanet.point.task.CirclePointTask" /> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="group" value="circle_point_group" /> <property name="name" value="circle_point_update" /> <!--false表示等上一个任务执行完后再开启新的任务 --> <property name="concurrent" value="false" /> <property name="targetObject"> <ref bean="taskJob" /> </property> <property name="targetMethod"> <value>run</value> </property> </bean> <!-- 调度触发器 --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="name" value="circle_point_update" /> <property name="group" value="circle_point_group" /> <property name="jobDetail"> <ref bean="jobDetail" /> </property> <property name="cronExpression"> <value>0 0 2? * *</value> </property> </bean> <!-- 调度工厂 --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="myTrigger" /> </list> </property> </bean> </beans>
这里配置的表达式是每天凌晨两点执行一次,指定定时任务实现类是CirclePointTask,方法是run。
3、定时任务实现类
package com.inspur.chinanet.point.task; import java.io.IOException; import java.sql.Date; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import com.inspur.chinanet.point.dao.JdbcImpl; import com.inspur.chinanet.point.util.DataUtil; import com.inspur.chinanet.point.util.LogUtil; import com.inspur.chinanet.point.util.PropertiesConfigUtil; import com.vividsolutions.jts.io.ParseException; /** * 定时任务实现类 * * @author wulinfeng * @version C10 2018年1月29日 * @since SDP V300R003C10 */ public class CirclePointTask { private static final Logger LOG = Logger.getLogger("CirclePointTask"); @Autowired private JdbcImpl jdbcImpl; /** * 定时任务执行方法 * * @author wulinfeng * @throws IOException * @throws ParseException */ public void run() throws IOException, ParseException { // 手动模式,无需处理 if ("0".equals(PropertiesConfigUtil.getProperty("isTimeTask"))) { return; } long startTime = System.currentTimeMillis(); try { // 处理日志 LogUtil.dealLog(LOG); LOG.info("Start Task ***********************************"); // 加载spring配置文件 DataUtil.processData(jdbcImpl, getOrderDates()); } catch (Exception e) { LOG.warning(e.getMessage()); } LOG.info("End ***********************************"); LOG.info("Cost time: " + (System.currentTimeMillis() - startTime) / 1000 + " second."); } /** * 获取order_date列表 * * @author wulinfeng * @return * @throws java.text.ParseException */ private List<Date> getOrderDates() throws java.text.ParseException { List<java.sql.Date> orderDates = new ArrayList<>(); String orderDateStr = PropertiesConfigUtil.getProperty("order_date_list"); if (StringUtils.isEmpty(orderDateStr)) { orderDates.add(new java.sql.Date(System.currentTimeMillis())); } else { LOG.info("The ORDER_DATE configed is : " + orderDateStr); String[] orderDateList = orderDateStr.split(","); for (String orderDate : orderDateList) { orderDates.add(DataUtil.strToDate(orderDate)); } } return orderDates; } }
从上面可以清晰的看到,quartz框架基本上只需要配置以下4个bean:
1、定时任务实现类:taskJob;
2、定时任务信息:jobDetail,主要信息包括,定时任务组group,定时任务名name,是否并发执行concurrent,执行目标targetObject(关联taskJob),执行方法名targetMethod;
3、定时任务调度触发器:myTrigger,同上,触发器组group,触发器名name,触发的定时任务jobDetail(关联上面jobDetail),触发时间规则cronExpression;
4、定时任务调度工厂:scheduler,关联调度触发器myTrigger。
以上4个bean从具体到上层,环环相扣,调用机制都由quartz框架实现。