是否可以从Web上下文中找到Spring非Web上下文?

时间:2011-09-16 15:13:50

标签: java spring war

我有一个Spring应用程序,它在Jetty的嵌入式实例中启动REST服务,它本身是从Spring启动的。

初始Spring上下文有一个集成和数据库层,并启动Jetty实例。 Jetty然后调用它自己的应用程序上下文文件,该文件公开REST服务。

我想知道是否有一些方法可以将初始Spring上下文暴露给从Jetty中运行的Web上下文。不幸的是,我无法部署完整的J2EE服务器,而且我不愿意从Web上下文运行所有内容,依赖Jetty来管理线程等。

2 个答案:

答案 0 :(得分:3)

我假设您在Jetty的web.xml中有ContextLoaderListener,这就是Spring Web上下文的创建方式。

  1. 删除ContextLoaderListener 来自jetty的web.xml(但保留context-paramcontextConfigLocation

  2. 子类ContextLoader,覆盖loadParentContext() 返回初始的Spring上下文。

  3. 创建ContextLoader的实例 启动Jetty后的子类。

  4. 致电initWebApplicationContext(context.getServletContext().getContext()) 在这个例子中,“context”是org.mortbay.jetty.servlet.Context

答案 1 :(得分:1)

所以我找到了一个更好的答案,基于上面的ericacm。更好的唯一原因是你仍然可以在web.xml文件中使用<load-on-startup>作为servlet。

嵌入Jetty服务器时,需要创建WebAppContext。超类ContextHandler允许您设置EventListener的数组,其中包含ServletContextListener

因此解决方案是扩展ContextLoader并实现Spring的ApplicationContextAwareServletContextListener接口。加载器允许您返回由contextaware接口设置的父上下文,并且侦听器通过ServletContext向您提供contextInitialized()

然后您可以在任何Jetty组件之前初始化它,并在Jetty服务器加载时访问完全填充的ServletContext,在任何Web应用程序自身初始化之前调用它。

监听器实现:

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.ContextLoader;

public final class EmbeddedJettySpringContextLoaderListener extends ContextLoader implements ApplicationContextAware, ServletContextListener
{
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * Returns the parent application context as set by the
     * {@link ApplicationContextAware} interface.
     * 
     * @return The initial ApplicationContext that loads the Jetty server.
     */
    @Override
    protected ApplicationContext loadParentContext(ServletContext servletContext) {
        return this.applicationContext;
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        super.initWebApplicationContext(sce.getServletContext());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //not needed
    }
}

WebAppContext的Jetty配置(最终由服务器引用):

<!-- Loads this application context as the parent of the web application context. -->
<bean id="parentContextLoaderListener" class="com.citi.matrix.server.restapi.EmbeddedJettySpringContextLoaderListener" />

<bean id="restApiWebAppContext" class="org.mortbay.jetty.webapp.WebAppContext">
  <property name="displayName" value="RestApi" />
  <property name="contextPath" value="/" />
  <!-- the value for war, must be a relative path to the root of the application, and does not use the classpath. -->
  <property name="war" value="${WEBAPPS_HOME}/rest-api" />
  <property name="eventListeners">
    <ref  local="parentContextLoaderListener" />
  </property>
  <property name="configurationClasses">
    <list>
      <value>org.mortbay.jetty.webapp.WebInfConfiguration</value>
      <value>org.mortbay.jetty.webapp.WebXmlConfiguration</value>
      <value>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</value>
    </list>
  </property>
  <property name="logUrlOnStart" value="true" />
</bean>