簡體   English   中英

Spring MVC和Quartz集成

[英]Spring MVC and Quartz integration

我想用Quartz Scheduler替換Spring MVC Webapp中的TimerTask。 我的spring-quartz.xml:

<bean id="manifestTask" class="it.dhl.wla.quartz.ManifestTask"  />
<bean id="manifestJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="manifestTask" />
    <property name="targetMethod" value="go" />
</bean>
<bean id="manifestTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail" ref="manifestJob" />
    <property name="cronExpression" value="59 15 * * * ?" />     
</bean>

它與空的go()方法一起工作(僅帶有日志輸出),問題出在我嘗試@Autowire的ManifstTask依賴項上:

public class ManifestTask {
@Autowired
ManifestService manifestService;

private static final Logger LOG = Logger.getLogger(ManifestTask.class);

public void go() {
    LOG.info("Manifest quartz task start...");
    boolean res=manifestService.doManifest();
    LOG.info("Manifest  quartz task end: "+res);
}
}

這是啟動時的錯誤:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [it.dhl.wla.service.ManifestService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

ManifestService在其他類中可以自動裝配並且可以工作,在這種石英任務的特定情況下,bean實例化順序似乎是一個問題。

Spring版本是3.0.5,Quartz 1.8.6。

編輯:

在ManifestTask中添加了對ApplicationContext的引用:

@Autowired
ApplicationContext appctx=null;

很好,當石英調用方法go()時,我瀏覽了appctx,但是找不到任何用注解聲明的@Components。 我發現在spring-quartz.xml中聲明的bean。

appctx的具體類是XmlWebApplicationContext。 xml聲明的bean是否在單獨的上下文中? 如何訪問帶注釋的@Components?

您應該使用@Component注釋ManifestTask ,以便在spring:D時使用。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ManifestTask {
    @Autowired
    ManifestService manifestService;

    private static final Logger LOG = Logger.getLogger(ManifestTask.class);

    public void go() {
        LOG.info("Manifest quartz task start...");
        boolean res=manifestService.doManifest();
        LOG.info("Manifest  quartz task end: "+res);
    }
}

另外,在查看編輯過的帖子后,我認為您應該閱讀以下答案:
如何將一個項目的spring-config.xml導入另一個項目的spring-config.xml?

我找到了解決方法,但是我不喜歡它。

spring-quartz.xml:

<!-- MANIFEST -->
<bean id="theManifestService" class="it.dhl.wla.service.ManifestService"/>
<bean id="manifestTask" class="it.dhl.wla.quartz.ManifestTask" >
    <property name="manifestService" ref="theManifestService"/>        
</bean>
<bean id="manifestJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="manifestTask" />
    <property name="targetMethod" value="go" />
</bean>
<bean id="manifestTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail" ref="manifestJob" />
    <property name="cronExpression" value="59 15 * * * ?" />   
</bean>

在ManifestTask.java中:

private ManifestService manifestService;

public ManifestService getManifestService() {
    return manifestService;
}

public void setManifestService(ManifestService manifestService) {
    this.manifestService = manifestService;
}

現在,ManifestService bean和依賴項已在xml中定義。 但是我的ManifestService類仍被注釋為@Component,因為我在某些控制器中使用了它。

我認為現在我有2個獨立的ManifestService實例...

請按照以下步驟將Quartz與Spring Boot集成在一起

1-在pom.xml文件中添加以下依賴項,它也需要spring-context-support

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

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>

2-創建單獨的xml並在現有的xml中添加以下代碼

<?xml version="1.0" encoding="UTF-8"?>

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

    <bean id="quartzJob" class="com.mightyjava.quartz.ExecuteUsingQuartz" />

    <bean id="jobFactoryBean" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
        p:targetObject-ref="quartzJob" p:targetMethod="run" />

    <bean id="triggerFactoryBean"
        class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"
        p:jobDetail-ref="jobFactoryBean" p:cronExpression="0/5 * * * * ?" />

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
        p:triggers-ref="triggerFactoryBean" />

</beans>

3-創建一個包含執行邏輯的類

import java.util.Date;

public class ExecuteUsingQuartz {
    public void run() { 
        System.out.println("Executing using quartz in every 15 seconds " + new Date());
    }
}

如果仍然有疑問,請單擊下面的鏈接並觀看現場演示

如何在Spring MVC中集成Quartz Scheduler?

我懷疑發生的事是在xxxx-servlet.xml Spring內容文件之一中掃描了ManifestService bean並將其實例化。 在yyyy-servlet.xml中處理/實例化bean時,以這種方式創建的bean不可用。

為了使bean對所有Spring上下文都全局可用,您需要掃描它所屬的包,或者在與Spring上下文加載器偵聽器關聯的applicationContext.xml文件中對其進行定義。 就像是:

web.xml

...
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM