Spring 调度系统

2019-05-20  本文已影响0人  索伦x

Spring 调度系统简介

一说到调度,Java 程序员马上就会想到 Quartz,但 Quartz 学习使用起来相对比较复杂。其实spring 3.0版本后,自带了一个定时任务工具,而且使用简单方便,不用配置文件,可以动态改变执行状态。也可以使用cron表达式设置定时任务,但被执行的类要实现Runnable接口。

第一个调度系统

<?xml version="1.0" encoding="UTF-8"?>
<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.suoron.springmvc</groupId>
    <artifactId>myShop-jobs</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>


    </dependencies>

</project>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- 字符集过滤器 -->
    <filter>
        <filter-name>encodingFilter</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- spring mvc 前端控制器 -->
    <servlet>
        <servlet-name>springServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd">

    <context:annotation-config />
    <context:component-scan base-package="com.suoron.springmvc.service.impl"/>

    <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler" init-method="initialize">
        <property name="poolSize" value="2"/>
    </bean>

</beans>

代码说明:

ThreadPoolTaskScheduler 是一个专门用于调度任务的类,实际上也实现了Spring的TaskExecutor接口,因此单个实​​例可以尽快用于异步执行,也可以用于计划和可能重复执行。

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <description>Spring MVC Configuration</description>

    <!-- 加载配置属性文件 -->
    <!--  <context:property-placeholder ignore-unresolvable="true" location="classpath:config.properties"/> -->

    <!-- 使用 Annotation 自动注册 Bean,只扫描 @Controller -->
    <context:component-scan base-package="com.suoron.springmvc.controller"/>

    <!-- 配置注解驱动 可以将request参数与绑定到controller参数上 -->
    <mvc:annotation-driven />


    <!-- html视图解析器 必须先配置freemarkerConfig,注意html是没有prefix前缀属性的-->
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath">
            <value>/WEB-INF/views/html</value>
        </property>
        <property name="defaultEncoding" value="UTF-8" />
    </bean>
    <bean id="htmlviewResolver"
          class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="suffix" value=".html" />
        <property name="order" value="0"></property>
        <property name="contentType" value="text/html;charset=UTF-8"></property>
    </bean>

    <!-- 定义视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->
        <property name="prefix" value="/WEB-INF/views/jsp/" />
        <property name="suffix" value=".jsp" />
        <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/> <!-- 不能用jstl的那个 -->
        <property name="contentType" value="text/html;charset=UTF-8"/>
        <property name="order" value="1"></property>
    </bean>

    <!-- 静态资源映射 -->
    <mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>
    <mvc:resources mapping="/json/**" location="/json/" cache-period="31536000"/>

</beans>
package com.suoron.springmvc.utils;

public class ScheduleTask implements Runnable {

    private String id;

    public String getId(){
        return id;
    }
    public ScheduleTask(String id){
        this.id = id;
    }

    public void run() {

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(System.currentTimeMillis() +":" + id+ " 开始执行!");
    }
}

package com.suoron.springmvc.service.impl;

import com.suoron.springmvc.service.JobService;
import com.suoron.springmvc.utils.ScheduleTask;
import org.springframework.scheduling.concurrent.ScheduledExecutorTask;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

@Service
public class JobServiceImpl implements JobService {

    @Resource
    ThreadPoolTaskScheduler taskExecutor;
    private static Map<String, ScheduledFuture<?>> scheduledFutureMap = new HashMap<String, ScheduledFuture<?>>();

    public void startJob(ScheduleTask scheduledTask, Date startTime) {
        ScheduledFuture<?> scheduledFuture = taskExecutor.schedule(scheduledTask, startTime);
        scheduledFutureMap.put(scheduledTask.getId(), scheduledFuture);
        System.out.println(startTime.getTime() + " 定时任务:" + scheduledTask.getId() + " 添加成功!!");
    }

    public void cancelJob(ScheduleTask scheduledTask) {
        ScheduledFuture<?> scheduledFuture = scheduledFutureMap.get(scheduledTask.getId());
        if(scheduledFuture != null && !scheduledFuture.isCancelled()){
            scheduledFuture.cancel(false);
            System.out.println(System.currentTimeMillis() + " 定时任务:" + scheduledTask.getId() + " 取消成功!!");
        }
        scheduledFutureMap.remove(scheduledTask.getId());
    }
}

代码说明:
TaskScheduler接口下定义了6个方法

  • schedule(Runnable task, Trigger trigger);
    指定一个触发器执行定时任务。可以使用CronTrigger来指定Cron表达式,执行定时任务
 CronTrigger t = new CronTrigger("0 0 10,14,16 * * ?");
 taskScheduler.schedule(this, t);
  • schedule(Runnable task, Date startTime);
    指定一个具体时间点执行定时任务,可以动态的指定时间,开启任务。只执行一次。(比Timer好用多了。早发现这接口就好了。。。)
  • scheduleAtFixedRate(Runnable task, long period);
    立即执行,循环任务,指定一个执行周期(毫秒计时)
    PS:不管上一个周期是否执行完,到时间下个周期就开始执行
  • scheduleAtFixedRate(Runnable task, Date startTime, long period);
    指定时间开始执行,循环任务,指定一个间隔周期(毫秒计时)
    PS:不管上一个周期是否执行完,到时间下个周期就开始执行
  • scheduleWithFixedDelay(Runnable task, long delay);
    立即执行,循环任务,指定一个间隔周期(毫秒计时)
    PS:上一个周期执行完,等待delay时间,下个周期开始执行
  • scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
    指定时间开始执行,循环任务,指定一个间隔周期(毫秒计时)
    PS:上一个周期执行完,等待delay时间,下个周期开始执行
    1. 动态添加任务WEB接口
@Controller
public class JobController {

    @Resource
    JobService jobService;

    @RequestMapping(value = "/job/start",method = RequestMethod.GET)
    @ResponseBody
    public String startJob(String id,long second){
        ScheduleTask scheduleTask = new ScheduleTask(id);
        jobService.startJob(scheduleTask,new Date(System.currentTimeMillis()+(second*1000)));
        return "success";
    }

    @RequestMapping(value = "/job/cancel",method = RequestMethod.GET)
    @ResponseBody
    public String testPage(String id){
        ScheduleTask scheduleTask = new ScheduleTask(id);
        jobService.cancelJob(scheduleTask);
        return "success";
    }
}

测试: http://localhost:8080/job/start?id=1&second=5

上一篇下一篇

猜你喜欢

热点阅读