Spring任务调度Quartz(后台服务)

什么是任务调度?

在生活中,我们经常会制定一些“计划任务”,即在某个时间点做某件事情。同样地,在企业级应用中,也会经常碰到类似的任务调度的需求,下面来看几个例子。

在购物网站,每天凌晨统计商品名、商家排名,每天晚上定点统计当日的销量、销售额、盈利等信息并生成报表,每15分钟查询用户的新订单并推送给对应处理人。
在社区网站,每天统计用户的在线时长,并按照某种规则给予一定的称号和奖励等。
在后台服务中做系统维护,每个工作日的固定时间将数据进行备份。
可见,企业应用中离不开灵活的任务调度。

业务情景

  • 1)规定在将来的某一特定的时间点执行设置业务。
  • 2)周期性反复执行特定业务。
  • 3)资源有效期控制 等等…

从以上例子可以看到,调度的核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个或一些操作。任务调度本身涉及多线程并发、运行时间规则解析、运行现场的保护与恢复及线程池维护等。这项非常复杂的工作,可以通过一个开源任务调度框架来实现,它就是Quartz框架。

任务调度就是后台服务

了解更多:前端,后端,前台,后台到底应该怎么理解。


Quartz与Spring的关系

Quartz框架是一个开源的企业级任务调度服务,它可以被单独使用,也可以整合进任何Java应用,从小型应用到大型的电子商务系统,Quartz已经被作为任务调度的良好解决方案。Quartz提供了强大的任务调度机制,使用也非常简单。Quartz允许开发人员灵活定义调度时间表,提供和任务进行关联的便捷方法,另外,Quartz提供了调度运行环境的持久化机制,使系统出现故障关闭时,任务调度现场数据可以保存下来不致丢失。

Quartz是一个强大的企业级任务调度框架,Spring中继承并简化了Quartz。


Cron 表达式

在这里插入图片描述
特殊字符

Cron 触发器利用一系列特殊字符,如下所示:

  • 反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。

  • 问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行。

  • 在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中,表示把执行安排在当月的第一个工作日内。

  • 井号(#)字符为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。

  • 星号(*)字符是通配字符,表示该字段可以接受任何可能的值。


Spring中怎样配置Quartz

基于AOP的 xml 配置
依赖项pom.xml文件:

	<properties>
        <spring.version>4.3.14.RELEASE</spring.version>
    </properties>
    <dependencies>
        <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>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

被调度的方法:

package com.uplooking.service;

import java.sql.Timestamp;
//任务调度执行方法
public class TeakService {
    public void hello(){
        System.out.println("Hello Quartz\t"+new Timestamp(System.currentTimeMillis()));
        /*
    说明:
    每秒中都进行数据库查询优惠券表,
    查询优惠券状态为正常(排除已经过期和使用过的优惠券),
    并且过期时间超过当前系统时间的优惠券,遍历设置为过去,并写入到日志中
     */
    }
}

我们在 applicationContext.xml 文件中配置 aop 自动生成代理,进行事务管理:

①、代理目标:要调用的工作类(com.uplooking.service)

②、代理业务:定义调用对象和调用对象的方法(hello)

③、计划安排: 定义触发时间(value="* * * * * ?" 表示每秒钟执行一次)

③、计划工厂:总管理类 如果将lazy-init='false’那么容器启动就会执行调度程序,可以不设置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
">
    <!-- 代理目标 -->
    <bean id="teakService" class="com.uplooking.service.TeakService"></bean>
    <!--代理业务-->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="teakService"></property>
        <property name="targetMethod" value="hello"></property>
    </bean>
    <!--计划安排-->
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail"></property>
        <property name="cronExpression" value="* * * * * ?"></property>
    </bean>
    <!-- 计划工厂 -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
            	<!-- 触发需要执行的时间计划 -->
                <ref bean="cronTrigger"></ref>
            </list>
        </property>
    </bean>
</beans>

启动任务

package com.uplooking.app;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
    	//容器启动就会执行调度程序
        String path="applicationContext.xml";
        ApplicationContext ctx=new ClassPathXmlApplicationContext(path);
    }
}

运行效果:
在这里插入图片描述

基于AOP的 注解 配置
  依赖项pom.xml文件:

	<properties>
        <spring.version>4.3.14.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
 	</dependencies>

被调度的方法:


package com.uplooking.service;


import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;

@Service("teakService")
public class TeakService {
    @Scheduled(cron = "* * * * * ?")
    public void hello(){
        System.out.println("@Scheduled Hello Quartz\t"+new Timestamp(System.currentTimeMillis()));
    }
}

分为如下两步:

①、在applicationContext.xml 配置任务调度器,将并事务管理器交予spring

②、在目标方法添加注解即可 @Scheduled

在 applicationContext.xml 文件中配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/task
       http://www.springframework.org/schema/task/spring-task-3.0.xsd
">
	<!-- 启动自动扫描注解 -->
    <context:component-scan base-package="com.uplooking.service"></context:component-scan>
    <!-- 启动任务调度 -->
    <task:annotation-driven></task:annotation-driven>
</beans>

启动任务

package com.uplooking.app;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        String path="applicationContext.xml";
        ApplicationContext ctx=new ClassPathXmlApplicationContext(path);
    }
}

运行效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你不懂、、、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值