0

我需要在部署战争时启动一个守护进程。守护进程本身使用应该用 Spring 注入的对象。我做了以下事情:

在 web.xml 中

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

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

应用监听器.java

public class AppListener implements ServletContextListener {
...
  @Override
  public void contextInitialized(final ServletContextEvent sce) {
      log.info("======================= Begin context init =======================");
      try {
        // final ApplicationContext context = new ClassPathXmlApplicationContext("WEB-INF/springapp-servlet.xml");
        final ApplicationContext context = new ClassPathXmlApplicationContext("src/main/webapp/WEB-INF/springapp-servlet.xml");
      //final ApplicationContext context = new ClassPathXmlApplicationContext("//Users/.../WEB-INF/springapp-servlet.xml");

      final SessionServiceDaemon sessionServiceDaemon = context.getBean(SessionServiceDaemon.class);
      sessionServiceDaemon.start();
    } catch (final Exception e) {
      log.error("Was not able to start daemon",e);
    }
}

SessionServiceDaemon.java

@Service
@Singleton
public class SessionServiceDaemon {

  private final static Logger log = LoggerFactory.getLogger(SessionServiceDaemon.class);

  private final SessionServiceHandler handler;

  @Inject
  public SessionServiceDaemon(final SessionServiceHandler handler) {
    log.info("+++++++++++++++++++++++++++++++ SessionServiceDaemon injected");
    this.handler = handler;
  }

我的 springapp-servlet.xml 只包含注入所需的包:

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

  <context:component-scan base-package="example" />
    <mvc:annotation-driven />

</beans>

在启动日志中,我看到了预期:

+++++++++++++++++++++++++++++++ SessionServiceDaemon injected

其次是

======================= Begin context init =======================

问题是:然后我得到一个异常,无论我使用哪个路径指向 springapp-servlet.xml,该文件都不存在:

org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [src/main/webapp/WEB-INF/springapp-servlet.xml]; nested exception is java.io.FileNotFoundException: class path resource [src/main/webapp/WEB-INF/springapp-servlet.xml] cannot be opened because it does not exist

我尝试了不同的相对路径,甚至是绝对路径都没有成功。我什至编辑了上面的代码,并在我尝试加载上下文的上方添加了以下内容:

  try {
    log.info(org.apache.commons.io.FileUtils.readFileToString(new File("src/main/webapp/WEB-INF/springapp-servlet.xml")));
  } catch (final Exception e) {
    log.error("Unable to find file",e);
  }

并且很好地打印了 springapp-servlet.xml 的内容。

我的2个问题:

  • 当我能够使用与同样的方法?
  • 无论如何,我是否有正确的方法来启动具有注入依赖项的守护程序?

PS:我使用Tomcat。

4

1 回答 1

1

您正在启动两个不同的 spring 应用程序上下文。第一个,内置的ContextLoaderListener,可能会从默认位置获取您的 springapp-servlet.xml 配置。(您没有说是否指定了 contextConfigLocation。)

然后,在您的自定义侦听器中,使用带有显式路径的 ClassPathXmlApplicationContext 构造一个新的应用程序上下文。在您显示的三行中,只有带有 ""WEB-INF/springapp-servlet.xml" 的行看起来可能是类路径解析的候选者,尽管它实际上取决于您如何配置和启动 Tomcat 实例。 (即,从 Tomcat 的角度来看,类路径是什么?)

无论如何,有更好的方法可以让 Spring 应用程序上下文进入 servlet/listener。一种直接的方法是像您一样使用 ContextLoaderListener,然后在您的自定义 servlet/listener 中使用 Spring 的WebApplicationContextUtils.getWebApplicationContext

Spring 也直接支持 servlet,包括通过注解配置、HttpServletBean类,甚至直接使用FrameworkServlet

于 2013-01-14T18:03:28.013 回答