Jetty - 在整合Spring的J2SE應用程式中嵌入Jetty的Web功能(應用和Web共用ApplicationContext)

襲冷發表於2018-05-17

一、說明

    如果開發了一個J2SE的應用程式,然後想用Web來完成一些的使用者介面,但是在啟動 Jetty 之前就已經建立和使用了 Spring 的 ApplicationContext了,但這些Web的業務中也要依賴於 Spring 的 ApplicationContext,這樣就會遇到一個問題:應用程式啟動後會建立一個 context,當Jetty啟動後又會建立一個 context,兩個不同的上下文將會產生重複載入和一些互動的問題。那麼能不能讓 Jetty 不建立新的 ApplicationContext,而直接共享使用之前應用程式所建立的呢?


二、建立Jetty啟動類

package com.xilen.util.spring;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;

/**
 * Jetty的啟動類
 * 實現 ApplicationContextAware,讓 Spring 傳入它的 ApplicationContext 並使用這個 Context
 */
public class SpringJettyStart implements ApplicationContextAware {

	private Server server;
	private ApplicationContext applicationContext;

	public void start() throws Exception {
		// 建立並設定 Server 的引數
		server = new Server();
		SelectChannelConnector connector = new SelectChannelConnector();
		connector.setPort(8080);
		server.addConnector(connector);
		
		// 建立並設定 WebAppContext 的引數
		WebAppContext webAppContext = new WebAppContext();
		webAppContext.setContextPath("/app");
		webAppContext.setDescriptor("webapps/app/WEB-INF/web.xml");
		webAppContext.setResourceBase("webapps/app");
		webAppContext.setConfigurationDiscovered(true);
		webAppContext.setParentLoaderPriority(true);
		server.setHandler(webAppContext);

		// 讓 WebApp 使用跟 ApplicationContext 同一個 ClassLoader
		webAppContext.setClassLoader(applicationContext.getClassLoader());

		// 自己建立 XmlWebApplicationContext
		XmlWebApplicationContext xmlWebAppContext = new XmlWebApplicationContext();
		xmlWebAppContext.setParent(applicationContext);
		xmlWebAppContext.setConfigLocation("");
		xmlWebAppContext.setServletContext(webAppContext.getServletContext());
		xmlWebAppContext.refresh();

		// 把建立的 XmlWebApplicationContext 傳入 WebAppContext 的 attribute 集合
		webAppContext.setAttribute( 
				WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, xmlWebAppContext);

		server.start();
	}

	/**
	 * 實現 ApplicationContextAware 介面,以讓 spring 把 application context 設定進來
	 */
	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;

	}

}
三、配置 Jetty 的啟動類到應用程式的 ApplicationContext 並執行它

<bean id="springJettyStart" class="com.xilen.util.spring.SpringJettyStart" init-method="start" />    
四、配置web.xml

     1、此時,將不再需要配置如下Spring相關的ContextLoaderListener和contextConfigLocation了

  <del><context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener></del>
    2、只需直接新增需要的Struts或Restlet等等

	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
        或

	<servlet>
		<servlet-name>restlet</servlet-name>
		<servlet-class>com.ericsson.smsc.correlation.restlet.eagle.EagleSpringServerServlet</servlet-class>
		<init-param>
			<param-name>org.restlet.application</param-name>
			<param-value>application</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>restlet</servlet-name>
		<url-pattern>/restlet/*</url-pattern>
	</servlet-mapping>

五、正常的啟動應用程式即可啟動這個和應用程式共用 ApplicationContext 的 Web 了。例如

	public static void main(String[] args){
		AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		applicationContext.registerShutdownHook();
	}

六、參考

    http://hippostart.iteye.com/blog/664972




相關文章