记录持久化的Quartz与Spring整合时遇到的几个坑

   由于工作,quartz需要持久化在数据库中,开启每日凌晨定时任务,在任务处理job中又需要使用到spring管理的service类,故遇到了几个小问题,以此做个记录。

  • 配置spring-quartz文件时,使用的MethodInvokingJobDetailFactoryBean创建jobDetail

     由于quartz使用了持久化,JobStoreTX存储方式,导致NotSerializableException异常。谷歌得知MethodInvokingJobDetailFactoryBean并未实现序列化,使用JobDetailFactoryBean方式创建,并在job类继承QuartzJobBean,创建jobDetail便不会出错。如下:

<!--使用JobDetailFactoryBean可序列化创建jobDetail-->
    <!--注入job,生成jobdetail-->
    <bean id="autoJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.pabj.newzg.xzg.message.utils.quartz.job.TimeQueryContract" />
        <!--持久化设置,允许持久化-->
        <property name="durability" value="true" />
    </bean>

——————————————————————————————————————————————————————————————————————————————————
//继承QuartzJobBean 类
@DisallowConcurrentExecution
public class TimeQueryContract extends QuartzJobBean {
    /**
     * Execute the actual job. The job data map will already have been
     * applied as bean property values by execute. The contract is
     * exactly the same as for the standard Quartz execute method.
     *
     * @param context
     * @see #execute
     */
    @Override
    protected void executeInternal(JobExecutionContext context) {...}
}

 

  • 注入spring管理的service的服务到job定时操作中,直接@Resource注入

 当时是直接报NullPointerException空指针异常,后又谷歌得知quartz有自己的上下文,spring管理不到,当然无法自动注入,改用在spring-quartz配置文件中直接将此service添加到jobDataMap中,

<!--注入job,生成jobdetail-->
    <bean id="autoJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.pabj.newzg.xzg.message.utils.quartz.job.TimeQueryContract" />
        <!--持久化设置,允许持久化-->
        <property name="durability" value="true" />

<!-- 将service添加到jobDataMap中,直接在job中通过context获取-->
        <property name="jobDataAsMap">
            <map>
                <entry key="contractSignService" value-ref="contractSignServiceImpl" />
            </map>
        </property>
    </bean>

 

这是一个方式可以解决没有持久化的quartz的service注入问题。但由于我的配置是需要持久化的,也就是需要存入数据库,需要序列化jobDetail。但spring的service底层没有实现Serializable接口,故报错NotSerializableException,自己实现Serializable也没用,其后谷歌很久,有重写相关类的方法,和使用sessionfactory,但本人能力还不行,没采用。后终在一位博主那看到将spring的context注入到quartz中

  • 在配置SchedulerFactoryBean时可注入spring上下文
<!--使用spring的Scheduler创建方式-->
<bean name="scheduler"     
 class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!--引用spring的数据源-->
        <property name="dataSource" ref="dataSource" />
        <!--读取quartz基本配置-->
        <property name="configLocation" value="classpath:quartz.properties" />

        <!--在此申明注入spring的上下文!!!-->
        <property name="applicationContextSchedulerContextKey"
                  value="applicationContextKey" />
        <!--设置自动启动-->

        <property name="autoStartup" value="true" />
        <!--动态修改存在的job-->
        <property name="overwriteExistingJobs" value="true" />
        <!--直接注入凌晨定时查询合同的job和trigger-->
        <property name="triggers">
            <list>
                <ref bean="createTrigger" />
            </list>
        </property>
    </bean>


————————————————————————————————————————————————————————————————————————————————————————
//在job中获取到spring上下文进行service调用
@DisallowConcurrentExecution
public class TimeQueryContract extends QuartzJobBean {
    /**
     * Execute the actual job. The job data map will already have been
     * applied as bean property values by execute. The contract is
     * exactly the same as for the standard Quartz execute method.
     *
     * @param context
     * @see #execute
     */
    @Override
    protected void executeInternal(JobExecutionContext context) {
        System.out.println("开始执行合同日期查询...");
       
        try {
            //获取spring上下文
            ApplicationContext applicationContextKey = (ApplicationContext) context.getScheduler().getContext().get("applicationContextKey");
            //获取service服务
            ContractSignServiceImpl contractSignService = (ContractSignServiceImpl) applicationContextKey.getBean("contractSignServiceImpl");
            System.out.println(contractSignService.queryDate().toString());
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

    }
}

最后解决方法的博主原文

 

走到这步,就解决了我快谷歌一天的难题。目前大概了解如此,算是解决了问题,做个记录,增强印象 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值