zoukankan      html  css  js  c++  java
  • Spring与Quartz的整合实现定时任务调度

    Quartz集成Spring的2个方法

    关于Spring集成Quartz有2种方法:

    1. JobDetailBean.

    2. MethodInvokeJobDetailFactoryBean.

    以下从自身使用和理解以及掌握的知识对其进行阐述。

    需要注意的是,在使用Spring集成Quartz的时候,一定不要忘记引入spring-support这个包:

    1、使用 MethodInvokeJobDetailFactoryBean

    applicationTask.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:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd">
        <!-- 定时任务 下游回调任务-->
        <!-- ======================== 1、定义需要执行的任务类。 ======================== -->
        <bean id="notifyQuartz" class="com.hsmpay.mobile.timerTask.NotifyTimerAction">
        </bean>
        <!-- ======================== 2、将需要执行的定时任务注入JOB中。 ======================== -->
        <bean id="notifyQuartzDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
             <!--引入执行任务的类-->
            <property name="targetObject"><ref bean="notifyQuartz"/></property>
            <!--定义要执行具体类的方法-->
            <property name="targetMethod"><value>remoteNotify</value></property>
        </bean>
        <!-- ======================== 3、调度触发器 ======================== -->
        <bean id="notifyTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    
            <property name="jobDetail"><ref bean="notifyQuartzDetail"/></property>
    
            <property name="cronExpression"> <!--每五分钟执行一次-->
                <!--<value>0 08 10 * * ?</value>-->
                <value>0 0/5 * * * ?</value><!--<value>秒 分 时 天 月 周 年</value> 0 55 17 ? * MON-FRI-->
            </property>
        </bean>
        <!--================================================================================================-->
    
        <!-- 半分钟执行定时任务 -->
        <!-- ======================== 1、定义需要执行的任务类。 ======================== -->
        <bean id="messageTask" class="com.hsmpay.mobile.timerTask.MessageTask"></bean>
        <!-- ======================== 2、将需要执行的定时任务注入JOB中。 ======================== -->
        <bean id="oneMessageRollBackTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <property name="targetObject"><ref bean="messageTask"/></property>
            <property name="targetMethod"><value>oneTaskJob</value></property>
        </bean>
        <!-- ======================== 3、调度触发器 ======================== -->
        <bean id="oneMessageStreamRollBackTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
            <property name="jobDetail">
                <ref bean="oneMessageRollBackTaskJobDetail"/>
            </property>
            <property name="cronExpression">
                <value>*/30 * * * * ?</value>
            </property>
        </bean>
    
    
    
        <!-- ======================== 4、调度工厂 ======================== -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="triggers">
                <list>
                    <ref bean="notifyTrigger"/>
                </list>
            </property>
        </bean>
    
        <bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
            <!-- 线程池维护线程的最少数量 -->
            <property name="corePoolSize" value="10" />
            <!-- 线程池维护线程所允许的空闲时间 -->
            <property name="keepAliveSeconds" value="200" />
            <!-- 线程池维护线程的最大数量 -->
            <property name="maxPoolSize" value="50" />
            <!-- 线程池所使用的缓冲队列 -->
            <property name="queueCapacity" value="100" />
            <property name="rejectedExecutionHandler">
                <!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 -->
                <!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 -->
                <!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
                <!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
                <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
            </property>
        </bean>
    </beans>

    相关代码配置

    @Controller("notifyTimerAction")
    public class NotifyTimerAction {
        private Logger log = LoggerFactory.getLogger(this.getClass());
        @Resource(name="transOrderService")
        TransOrderService transOrderService;//查询订单service
        //设置核心池大小
        int corePoolSize = 5;
        //设置线程池最大能接受多少线程
        int maximumPoolSize=20;
        //当前线程数大于corePoolSize、小于maximumPoolSize时,超出corePoolSize的线程数的生命周期
        long keepActiveTime = 200;
        //设置时间单位,秒
        TimeUnit timeUnit = TimeUnit.SECONDS;
    
        public String url ="http://localhost:8080/mobile/forwardPort/port.action";
    
    
        /**
         * 下游回调通知,继续发送
         */
        public void remoteNotify() throws Exception{
            log.debug("test定时任务启动了!!!!!!!!");
            System.out.println("test定时任务启动了!!!!!!!!");
            TransOrder order=new TransOrder();
            order.setStatus(1);//设置成功状态
            order.setClientType(7);//设置客户类型 7外放接口类型
            order.setOrderTypeId(1L);//收款类型
            //设置线程池缓存队列的排队策略为FIFO,并且指定缓存队列大小为5
            BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5);
            //创建ThreadPoolExecutor线程池对象,并初始化该对象的各种参数
            ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepActiveTime, timeUnit,workQueue);
            try {
                List<TransOrder> orderList = transOrderService.searchEntityList(order);
                Map<String,Object> map=new HashMap<String,Object> ();
                //准备给下游发送数据
                for(TransOrder transOrder:orderList){
                Thread thread=new Thread(new Runnable() {
                    public void run() {
                    map.put("status",transOrder.getStatus());//交易状态
                    map.put("orderNum",transOrder.getOrderNum());//订单号
                    JSONObject jsonObject = JSONObject.fromObject(map);
                    HttpClientUtil.submitPost(transOrder.getOtherData(), map.toString(), "UTF-8",60000, 60000);
                    }
                });
                  executor.execute(thread);
                }
                executor.shutdown();//关闭线程池
    
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            }
    
        }
    
    }
    

    ==================================================================================================================================================================

    二、JobDetailBean

    1. 创建一个Job方法,此方法必须继承QuartzJobBean或者实现Job方法。

    public class TestJob extends QuartzJobBean {
        
        @Override
        protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
            System.out.println(TimeUtils.getCurrentTime());
        }
    }

    2. 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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
            <property name="jobClass" value="com.mc.bsframe.job.TestJob"></property>
            <property name="durability" value="true"></property>
        </bean>
    
        <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
            <property name="jobDetail" ref="jobDetail" />
            <property name="startDelay" value="3000" />
            <property name="repeatInterval" value="2000" />
        </bean>
    
        <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
        <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <!-- 管理trigger -->
            <property name="triggers">
                <list>
                    <ref bean="simpleTrigger" />
                </list>
            </property>
        </bean>
    </beans>

    综上:定时任务的基本配置完成。

    三、两种方法的说明

    使用QuartzJobBean,需要继承。而使用MethodInvokeJobDetailFactoryBean则需要指定targetObject(任务实例)和targetMethod(实例中要执行的方法)

    后者优点是无侵入,业务逻辑简单,一目了然,缺点是无法持久化(目前还不太清楚这点!)

    从我使用的经验来说,我更推荐的第一种,其中一个很重要的原因就是因为定时任务中注入相关Service的时候,后者可以直接注入,而前者还需要进行Schedular的替换修改。

      

  • 相关阅读:
    Oracle客户端安装与配置
    Word VBA(批量复制Excel表格和Word表格到Word中)
    批量追加数据库(GDB,MDB,Shp)
    批量横向打印Excel
    重命名要素类
    删除GIS数据属性值空格(GDB,MDB,Shp)
    删除GIS数据库空层(GDB,MDB,Shape)
    批量裁剪GIS数据(包含GDB,MDB,Shp)
    批量裁剪GDB
    3DS文件导出MultiPatch
  • 原文地址:https://www.cnblogs.com/a8457013/p/8515917.html
Copyright © 2011-2022 走看看