美文网首页
Spring 调度系统

Spring 调度系统

作者: 索伦x | 来源:发表于2019-05-20 10:30 被阅读0次

    Spring 调度系统简介

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

    第一个调度系统

      1. POM.xml
    <?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>
    
      1. web.xml
    <?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>
    
    
      1. spring-context.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: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接口,因此单个实​​例可以尽快用于异步执行,也可以用于计划和可能重复执行。

    • 4.spring-mvc.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: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>
    
      1. 任务类
    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+ " 开始执行!");
        }
    }
    
    
      1. 调度接口实现类
    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

    相关文章

      网友评论

          本文标题:Spring 调度系统

          本文链接:https://www.haomeiwen.com/subject/rxoqzqtx.html