Quartz与Spring整合进行热部署的实现(二)

Spring的org.springframework.scheduling.quartz.JobDetailBean提供Job可序列化的实现(具体实现可查看源码)

此时.我们原来的job就可以继承QuartzJobBean,便会自动序列化到数据库,quartz的具体配置文件如下

<?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:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx" 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/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"
    default-lazy-init="true">

    <description>quartz配置</description>

    <!-- quartz使用的数据源配置 -->
    <bean id="quartzDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${quartz.jdbc.driver}" />
        <property name="url" value="${quartz.jdbc.url}" />
        <property name="username" value="${quartz.jdbc.username}" />
        <property name="password" value="${quartz.jdbc.password}" />
    </bean>

    <!-- 另一个事务管理器, Jdbc单数据源事务 -->
    <bean id="quartzTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="quartzDataSource" />
    </bean>

    <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="dataSource" ref="quartzDataSource"/>
        <property name="applicationContextSchedulerContextKey" value="applicationContext"/>
        <property name="configLocation" value="classpath:quartz.properties"/><!--
        这个是必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动
        -->
        <property name="startupDelay" value="30"/><!--
        这个是可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        -->
        <property name="overwriteExistingJobs" value="true"/>
        <property name="jobDetails" >
            <list>
                <ref bean="serverHealthJobDetail"/>
            </list>
        </property>
    </bean>

    <!-- 运行次数记录 -->
    <bean id="serverHealthJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
        <!--requestsRecovery属性为true,则当Quartz服务被中止后,再次启动任务时会尝试恢复执行之前未完成的所有任务-->
        <property name="requestsRecovery" value="true"/>
        <!-- 标识job是持久的,删除触发器的时候不被删除 -->
        <property name="durability" value="true"/>
        <property name="jobClass" value="cn.yzzn.hvac.quartz.job.ServerHealthJob"/>
    </bean>

</beans>

我们看到<property name="applicationContextSchedulerContextKey" value="applicationContext"/>此标签

Spring会帮我们自动注入applicationContext.并非上一篇文章中,通过Spring的工具手动获取applicationContext.

ServerHealthJob代码如下

public abstract class JobSupport extends QuartzJobBean {

    private BuildingManager buildingManager;
    private PlcManager plcManager;

    private static Logger logger = LoggerFactory.getLogger(JobSupport.class);

    private ApplicationContext applicationContext;
    /**
     * 从SchedulerFactoryBean注入的applicationContext.
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public <T> T getBean(String beanName, Class<T> clazz) {
        return this.applicationContext.getBean(beanName, clazz);
    }

    @Override
    protected void executeInternal(JobExecutionContext context)
            throws JobExecutionException {
        if (ObjectUtils.isNullOrEmptyString(buildingManager)) {
            buildingManager = getBean("buildingManager", BuildingManager.class);
        }
        if (ObjectUtils.isNullOrEmptyString(plcManager)) {
            plcManager = getBean("plcManager", PlcManager.class);
        }

        List<Building> buildingList = buildingManager.getBuildings();

        int size = buildingList.size();
        for (int i = 0; i < size; i++) {
            Building building = buildingList.get(i);

            Set<Plc> plcSet = building.getPlcs();
            for (Plc plc : plcSet) {
                innerIter(building, plc, i, size);
            }
        }
    }

    public abstract void innerIter(Building building, Plc plc,
            int index, int size);

}
public class ServerHealthJob extends JobSupport {

    @Override
    public void innerIter(Building building, Plc plc, int index, int size) {
        // TODO Auto-generated method stub

    }

}

ServerHealthJob就可以被Spring轻松的序列化到数据库.解决了上篇博文中繁琐的操作.

JobSupport是本人系统业务需求,同学们可自定义实现只要继承QuartzJobBean即刻.

数据库中已存在次jobDetail

TriggerManager也没多大变化

/**
 * Quartz Scheduler 管理类
 * 不带groupName参数的方法都采用自动填充默认组的形式 Scheduler.DEFAULT_GROUP
 * @author PigWing
 *
 */
public class SchedulerManagerImpl implements SchedulerManager {

    private QuartzDao quartzDao;
    private Scheduler scheduler;

    private static Logger logger = LoggerFactory.getLogger(UserController.class);

    /***
     * 增加一个触发器任务,采用默认组形式
     */
    public void addTrigger(String triggerName, String jobName,
            String cronExpression) throws SchedulerException, ParseException {
        addTrigger(triggerName, Scheduler.DEFAULT_GROUP, jobName, Scheduler.DEFAULT_GROUP, cronExpression);
    }

    /**
     *
     * 增加一个触发器任务
     */
    public void addTrigger(String triggerName, String triggerGroupName,
            String jobName, String jobGrourpName, String cronExpression) throws SchedulerException, ParseException {
        if(StringUtils.isEmpty(triggerName)) {
            throw new RuntimeException("triggerName can not be null");
        }

        try {
            JobDetail jobDetail = scheduler.getJobDetail(jobName, jobGrourpName);
            if(jobDetail != null) {
                scheduler.addJob(jobDetail, true);
                CronTrigger cronTrigger = new CronTrigger(triggerName, triggerGroupName, jobDetail.getName(), jobGrourpName);
                cronTrigger.setCronExpression(cronExpression);
                scheduler.scheduleJob(cronTrigger);
                scheduler.rescheduleJob(cronTrigger.getName(), cronTrigger.getGroup(), cronTrigger);
            }else {
                logger.error("cant not find jobDetail: " + jobGrourpName);
            }
        }catch(SchedulerException e) {
            logger.error(e.getMessage());
            throw e;
        }
    }

    /**
     * 返回所有触发器信息
     */
    public List<Map<String, Object>> getAllTriggers() {
        return quartzDao.getQuartzTriggers();
    }

    /**
     * 停止触发器
     */
    public void parseTrigger(String triggerName, String groupName)
            throws SchedulerException {
        try {
            scheduler.pauseTrigger(triggerName, groupName);
        }catch(SchedulerException e) {
            logger.error(e.getMessage());
            throw e;
        }

    }

    /**
     * 停止触发器,采用默认组形式
     */
    public void parseTrigger(String triggerName) throws SchedulerException {
        parseTrigger(triggerName, Scheduler.DEFAULT_GROUP);

    }

    /**
     * 重启触发器
     */
    public void resumeTrigger(String triggerName, String groupName)
            throws SchedulerException {
        try {
            scheduler.resumeTrigger(triggerName, groupName);
        }catch(SchedulerException e) {
            logger.error(e.getMessage());
            throw e;
        }

    }

    /**
     * 重启触发器,采用默认组形式
     */
    public void resumeTrigger(String triggerName) throws SchedulerException {
        resumeTrigger(triggerName, Scheduler.DEFAULT_GROUP);
    }

    /**
     * 移除触发器
     */
    public boolean removeTrigger(String triggerName, String groupName)
            throws SchedulerException {
        try {
            parseTrigger(triggerName, groupName);
            return scheduler.unscheduleJob(triggerName, groupName);
        }catch(SchedulerException e) {
            logger.error(e.getMessage());
            throw e;
        }
    }

    /**
     * 移除触发器,采用默认组形式
     */
    public boolean removeTrigger(String triggerName) throws SchedulerException {
        try {
            return removeTrigger(triggerName, Scheduler.DEFAULT_GROUP);
        }catch(SchedulerException e) {
            logger.error(e.getMessage());
            throw e;
        }
    }

    /**
     * 返回所有的任务名称
     */
    public String[] getJobNames(String groupName) throws SchedulerException {
        return scheduler.getJobNames(groupName);
    }

    public String[] getJobNames() throws SchedulerException {
        return scheduler.getJobNames(Scheduler.DEFAULT_GROUP);
    }

    @Autowired
    public void setQuartzDao(QuartzDao quartzDao) {
        this.quartzDao = quartzDao;
    }

    @Autowired
    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

}

本文转自:http://www.cnblogs.com/pigwing/archive/2011/07/12/2104002.html

时间: 2024-09-30 07:03:31

Quartz与Spring整合进行热部署的实现(二)的相关文章

Quartz与Spring整合进行热部署的实现(一)

先来几张实现图 任务管理页 新建任务管理.目前实现叫简单的需求...若各位同学要实现复杂的设计...quartz都有提供强大的支持.小弟目前的需求做到这已经够用了. 接下来.我们如何实现quartz的热部署编码呢? 小弟是利用spring整合quzrtz实现的.但是会产生两个小问题. 我们先看看quartz如何与spring整合 <bean name="quartzScheduler" class="org.springframework.scheduling.quar

Eclipse Spring boot项目热部署

spring boot项目 热部署 一,参考文档:springboot 热部署 note: 1.使用eclipse: project-->Build Automatically (选中) 2.Digital Twin 项目使用Spring boot 版本为:1.2.3.RELEASE,使用spring-boot-devtools无效. 查看Spring-boot-devtools,最低版本为1.3.0. 猜测Spring boot 整合Spring-boot-devtools最低版本为1.3.0

IDEA中Spring boot配置热部署无效问题解决方式(转)

IDEA中Spring boot配置热部署无效问题解决方式 2018年01月31日 20:30:59 阅读数:1426 该配置方式属于通过配置devtools实现热部署 只要在pom文件中添加下面代码段即可 <!-- 热部署 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId>

Spring整合JMS-基于activeMQ实现(二)

Spring整合JMS-基于activeMQ实现(二) 1.消息监听器 在Spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageListener.SessionAwareMessageListener.MessageListenerAdapter 1.1 MessageListener MessageListener是最原始的消息监听器(javax.jms.MessageListener),它是JMS规范中定义的一个接口.定义了一个omMe

spring boot 之热部署(三)

热部署:当发现程序修改时自动启动应用程序. spring boot使用的是spring-boot-devtools是一个为开发者服务的一个模块.其原理用了classLoader 其中一个加载不变的类,另一个restart ClassLoader加载变得类. devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机). 不说废话,我喜欢的Coding就是简单and直接.我写代码一般都是截图,不会粘代码,目的是让你们能敲一遍,我认为程序是敲出来的不是看出来的.你们要懂

spring boot 调试 - 热部署

命令行方式: mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" 需要在idea 中edit configuration->+ -> remote->debug rum main方法: debug run 热部署 在pom里添加: <build> <plugins> <p

IDEA 中 Spring Boot 启用热部署

maven 配置 <?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/

1. Spring boot 之热部署

1. spring boot 热部署 1.1. springloaded springloaded可以实现修改类文件的热部署.下载地址:springloaded 安装单击Run Configurations... 在Arguments标签页的vm arguments中填入如下内容,注意下面指定的springloaded路径: -javaagent:F:\sortingData\maven\Repositories\Maven\org\springframework\springloaded\1.

Spring Boot实现热部署

在Spring Boot实现代码热部署是一件很简单的事情,代码的修改可以自动部署并重新热启动项目. 引用devtools依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> 这