我有一个Spring应用程序,它在Jetty的嵌入式实例中启动REST服务,它本身是从Spring启动的。
初始Spring上下文有一个集成和数据库层,并启动Jetty实例。 Jetty然后调用它自己的应用程序上下文文件,该文件公开REST服务。
我想知道是否有一些方法可以将初始Spring上下文暴露给从Jetty中运行的Web上下文。不幸的是,我无法部署完整的J2EE服务器,而且我不愿意从Web上下文运行所有内容,依赖Jetty来管理线程等。
答案 0 :(得分:3)
我假设您在Jetty的web.xml中有ContextLoaderListener
,这就是Spring Web上下文的创建方式。
删除ContextLoaderListener
来自jetty的web.xml(但保留context-param
与contextConfigLocation
)
子类ContextLoader
,覆盖loadParentContext()
返回初始的Spring上下文。
创建ContextLoader
的实例
启动Jetty后的子类。
致电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的ApplicationContextAware
和ServletContextListener
接口。加载器允许您返回由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>