与spring集成实际就是将Jobdetail、Trigger、Scheduler交给spring管理。常用的集成方式每个都有两种
1. 使用Quartz配置作业(JobDetail)两种方式:
MethodInvokingJobDetailFactoryBean
JobDetailFactoryBean
方式一:使用MethodInvokingJobDetailFactoryBean(简单,需要注入一个执行任务的bean对象和执行的方法名称)
1.调用firstBean的printMessage方法
2.FirstBean类(普通的java类,交给spring管理)
package cn.qlq.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.stereotype.Component; @Component("firstBean") public class FirstBean { public void printMessage() { // 打印当前的执行时间,格式为2017-01-01 00:00:00 Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("FirstBean Executes!" + sf.format(date)); } }
方式二:使用JobDetailFactoryBean(想要更加灵活的话就是用这种方式,可以使用jobDataMap传递参数)
1.需要给作业传递数据,想要更加灵活的话就是用这种方式
2.FirstScheduleJob类(继承QuartzJobBean,重写executeInternal方法,使用jobDataMap注入一个SecondBean)
package cn.qlq.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.springframework.scheduling.quartz.QuartzJobBean; public class FirstScheduledJob extends QuartzJobBean{ private SecondBean secondBean; public void setSecondBean(SecondBean secondBean) { this.secondBean = secondBean; } @Override protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { //可以获取JobDetail的标识信息 JobKey key = arg0.getJobDetail().getKey(); System.out.println("job key:"+"name "+key.getName()); System.out.println("job key:"+"group "+key.getGroup()); Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("FirstScheduledJob Executes!" + sf.format(date)); this.secondBean.printMessage(); } }
3.SecondBean .java
package cn.qlq.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.stereotype.Component; @Component("secondBean") public class SecondBean { public void printMessage() { // 打印当前的执行时间,格式为2017-01-01 00:00:00 Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("SecondBean Executes:" + sf.format(date)); } }
2. trigger也有两种常见的配置方式(SimpleTrigger和CronTrigger)----需要将JobDetail注入到trigger中
1.第一种:simpletrigger
<!-- 第一种: 距离当前时间1秒之后执行,之后每隔两秒钟执行一次(SimpleTrigger用法) --> <bean id="mySimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="simpleJobDetail"/> <property name="startDelay" value="1000"/> <property name="repeatInterval" value="2000"/> </bean>
2.第二种:cronTrigger
<!-- 第二种:每隔5秒钟执行一次 (CronTrigger用法)--> <bean id="myCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="firstComplexJobDetail"/> <property name="cronExpression" value="0/5 * * ? * *"/> </bean> <bean id="fetchDataTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="fetchDataJobDetail"/> <property name="cronExpression" value="0/5 * * ? * *"/> </bean>
3.Scheduler也有两种配置方式:
1.第一种:分别注入JobDetails和Triggers
<!-- 第一种:Schduler的创建以及指定jobDetail和trigger--> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="jobDetails"> <list> <ref bean="simpleJobDetail"/> <ref bean="firstComplexJobDetail"/> </list> </property> <property name="triggers"> <list> <ref bean="mySimpleTrigger"/> <ref bean="myCronTrigger"/> </list> </property> </bean>
2.第二种:只注入triggers,实际是在第一种的基础上取消注入jobDetails
<!--第二种方式:只指定trigger --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="fetchDataTrigger"/> <!--<ref bean="fetchDataTrigger2"/> --> </list> </property> </bean>
------------------------- 例如:两种方式与spring整合的完整例子:--------------------------------
0.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>cn.qlq</groupId> <artifactId>SpringQuartz</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <!-- 声明变量,下面用类似于el表达式提取 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.3.6.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </dependency> <!-- JSP和Servlet的包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> </dependency> </dependencies> <build> <!-- 配置了很多插件 --> <plugins> <!-- 编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- tomcat7插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>80</port> <path>/springQuartz</path> <uriEncoding>UTF-8</uriEncoding> <server>tomcat7</server> </configuration> </plugin> </plugins> </build> </project>
1.applicationContext.xml (quartz配置在这里,注意两种定义jobDetail的方法)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd "> <!-- 扫描@Controler @Service --> <context:component-scan base-package="cn.qlq" /> <!-- 1.JobDatail的两种创建方式 --> <!--第一种: 用MethodInvokingJobDetailFactoryBean创建第一个简单的JobDetail,执行FirstBean的 printMessage方法 --> <bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="firstBean" /> <property name="targetMethod" value="printMessage" /> </bean> <bean id="fetchDataJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="fetchData" /> <property name="targetMethod" value="work" /> </bean> <!--第二种:用JobDetailFactoryBean创建一个jobDetail --> <bean id="firstComplexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <!-- 指明QuartzJobBean的类全路径 --> <property name="jobClass" value="cn.qlq.quartz.FirstScheduledJob" /> <!-- 使用jobDataMap传入数据(map的key与属性名相同且属性要有set方法) --> <property name="jobDataMap"> <map> <entry key="secondBean" value-ref="secondBean" /> </map> </property> <property name="Durability" value="true" /> </bean> <!-- 2.两种Trigger的创建--> <!-- 第一种: 距离当前时间1秒之后执行,之后每隔两秒钟执行一次(SimpleTrigger用法) --> <bean id="mySimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="simpleJobDetail"/> <property name="startDelay" value="1000"/> <property name="repeatInterval" value="2000"/> </bean> <!-- 第二种:每隔5秒钟执行一次 (CronTrigger用法)--> <bean id="myCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="firstComplexJobDetail"/> <property name="cronExpression" value="0/5 * * ? * *"/> </bean> <bean id="fetchDataTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="fetchDataJobDetail"/> <property name="cronExpression" value="0/5 * * ? * *"/> </bean> <!-- 3. 两种 scheduler的创建方式。二选一即可--> <!-- 第一种:Schduler的创建以及指定jobDetail和trigger--> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="jobDetails"> <list> <ref bean="simpleJobDetail"/> <ref bean="firstComplexJobDetail"/> </list> </property> <property name="triggers"> <list> <ref bean="mySimpleTrigger"/> <ref bean="myCronTrigger"/> </list> </property> </bean> <!--第二种方式:只指定trigger --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="fetchDataTrigger"/> <!--<ref bean="fetchDataTrigger2"/> --> </list> </property> </bean> </beans>
2.springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <!-- 处理请求返回json字符串的中文乱码问题 --> <!-- 设定消息转换的编码为utf-8防止controller返回中文乱码 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> </list> </property> </bean> <mvc:annotation-driven/> <!-- 视图解释器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
3.web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>springmvc-mybatis</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- Spring监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 处理POST提交乱码问题 --> <filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <!-- 前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 默认找 /WEB-INF/[servlet的名称]-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 1. /* 拦截所有 jsp js png .css 真的全拦截 建议不使用 2. *.action *.do 拦截以do action 结尾的请求 肯定能使用 ERP 3. / 拦截所有 (不包括jsp) (包含.js .png.css) 强烈建议使用 前台 面向消费者 www.jd.com/search /对静态资源放行 --> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
4.主要的java类:
FirstBean.java
package cn.qlq.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.stereotype.Component; @Component("firstBean") public class FirstBean { public void printMessage() { // 打印当前的执行时间,格式为2017-01-01 00:00:00 Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("FirstBean Executes!" + sf.format(date)); } }
SecodeBean.java
package cn.qlq.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.stereotype.Component; @Component("secondBean") public class SecondBean { public void printMessage() { // 打印当前的执行时间,格式为2017-01-01 00:00:00 Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("SecondBean Executes:" + sf.format(date)); } }
FirstScheduledJob.java
package cn.qlq.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.springframework.scheduling.quartz.QuartzJobBean; public class FirstScheduledJob extends QuartzJobBean{ private SecondBean secondBean; public void setSecondBean(SecondBean secondBean) { this.secondBean = secondBean; } @Override protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { //可以获取JobDetail的标识信息 JobKey key = arg0.getJobDetail().getKey(); System.out.println("job key:"+"name "+key.getName()); System.out.println("job key:"+"group "+key.getGroup()); Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("FirstScheduledJob Executes!" + sf.format(date)); this.secondBean.printMessage(); } }
结果:
FirstBean Executes!2018-04-05 16:57:18 job key:name firstComplexJobDetail job key:group DEFAULT FirstScheduledJob Executes!2018-04-05 16:57:20 SecondBean Executes:2018-04-05 16:57:20 FirstBean Executes!2018-04-05 16:57:20 FirstBean Executes!2018-04-05 16:57:22 FirstBean Executes!2018-04-05 16:57:24 job key:name firstComplexJobDetail job key:group DEFAULT FirstScheduledJob Executes!2018-04-05 16:57:25 SecondBean Executes:2018-04-05 16:57:25 FirstBean Executes!2018-04-05 16:57:26 FirstBean Executes!2018-04-05 16:57:28 job key:name firstComplexJobDetail job key:group DEFAULT FirstScheduledJob Executes!2018-04-05 16:57:30 SecondBean Executes:2018-04-05 16:57:30 FirstBean Executes!2018-04-05 16:57:30
.......
总结:
spring整合quartz的时候也是将quartz的三个主要元素交给spring管理,JobDatail、Trigger、Scheduler。
JobDetail有两种方式,MethodInvokingJobDetailFactoryBean 和 JobDetailFactoryBean (推荐这种,更加灵活,可以传入利用jobDataMap参数),需要将执行任务的bean和bean的方法注入
Trigger主要也是使用SimpleTrigger和CronTrigger(推荐这种,更加灵活),需要将jobDetail传入Trigger
Scheduler使用SchedulerFactoryBean工厂创建,需要传入jobDetails集合(可选,不注入这个也可以)和triggers集合,可以配置多个jobDetail(可选,可以不注入)和Trigger
在测试的时候我们可以先http接口进行测试,一般定时任务也会暴露一个http接口 进行手动的进行定时任务的操作。而且定时任务最好不要太过于频繁的拉取数据,类似于同步拉取数据等操作最好是夜间进行操作。不过具体的也是看业务需求。。。。。。。。。。。。。。。。。。。。。。
当然也可以用java.util.concurrent并发包中的ScheduledThreadPoolExecutor内容实现任务调度的功能,参考:https://www.cnblogs.com/qlqwjy/p/9470414.html
一个定时打印信息与定时获取http接口信息的Git地址: https://github.com/qiao-zhi/SpringQuartz