jetty作为一个轻量级的Servlet容器用来作为嵌入的Servlet服务器非常方便。通过Spring mvc 的相关文档的理解,试验了几种jetty 集成Spring Mvc的方法,进行记录。
1、通过web.xml方式配置集成
public class JettyServer {
public static void main(String[] args) throws Exception {
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8091);
server.setConnectors(new Connector[] { connector });
String webappPath = Paths.get(JettyServer.class.getClassLoader().getResource(".").toURI()).toAbsolutePath().toString();
WebAppContext context = new WebAppContext( webappPath,"/");
server.setHandler(context);
server.start();
// 打印dump时的信息
System.out.println(server.dump());
// join当前线程
server.join();
}
}
web.xml的位置在:
resources:
WEB-INF:
web.xml
配置文件的内容可以参考:
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
/WEB-INF/app-context.xml
app
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/app-context-mvc.xml
1
app
/app/*
上面的代码,在创建WebAppContext的时候指定了具体webapp的路径为项目的起始目录(编译后运行的起始目录)。没有通过代码明确指定web.xml的位置,猜测javaEE规范规定了 Servlet容器自动的寻找webapp下WEB-INF目录下的web.xml进行加载。web.xml中指定了Spring Mvc 的配置。
2、通过jetty的设置配置DispatcherServlet
public class ManualJettyServer {
private static String CONTEXT_PATH = "/";
private static String MAPPING_URL = "/*";
public static void main(String[] args) throws Exception {
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8090);
server.setConnectors(new Connector[] { connector });
WebAppContext context = new WebAppContext();
ServletContextHandler handler = servletContextHandler(webApplicationContext());
server.setHandler(handler);
// 启动
server.start();
// 打印dump时的信息
System.out.println(server.dump());
// join当前线程
server.join();
}
private static ServletContextHandler servletContextHandler(WebApplicationContext context) {
ServletContextHandler handler = new ServletContextHandler();
handler.setContextPath(CONTEXT_PATH);
handler.addServlet(new ServletHolder(new DispatcherServlet(context)), MAPPING_URL);
handler.addEventListener(new ContextLoaderListener(context));
return handler;
}
private static WebApplicationContext webApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MvcConfig.class);
return context;
}
}
上述代码通过jetty的api 完成对Spring Mvc Context的配置和设置。
3、通过ServletContainerInitializer 自动探测
Servlet 3.0 新增了接口;ServletContainerInitializer。Servlet规范规定了Servlet 容器在启动时依据Java SPI动态获取ServletContainerInitializer接口的服务(META-INF/services/javax.servlet.ServletContainerInitializer文件,内容就是ServletContainerInitializer实现类的全限定名),并执行其onStartup()方法,onStartup的方法定义如下:
public interface ServletContainerInitializer {
void onStartup(Set> c, ServletContext ctx) throws
ServletException;
}
在实现 Servlet(ontainerInitializer 时还可以通过 HandlesTypes 注解定义本实现类希望处理的类型,容器会将当前应用中所有这一类型(继承或者实现)的类放在方法onStartup参数中传递进来。如果不定义处理类型,或者应用中不存在相应的实现类,则集合参数c 为空。
Spring MVC提供了SpringServletContainerInitializer 来被Servlet 容器启动过程中探测调用。
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
}
基于以上Spring MVC提供的支持,可以让jetty自动探测加载相关的DispatchServlet的配置。
public class ContainerInitializerDemo implements WebApplicationInitializer {
public static void main(String[] args) throws Exception {
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8090);
server.setConnectors(new Connector[] { connector });
String webappPath = JettyServer.class.getClassLoader().getResource(".").getPath();
WebAppContext context = new WebAppContext( webappPath.substring(1),"/");
MetaData metaData = context.getMetaData();
Resource webappInitializer = Resource.newResource(JettyServer.class.getClassLoader().getResource("."));
metaData.addContainerResource(webappInitializer);
context.setConfigurations(new Configuration[] {
new AnnotationConfiguration(),
new WebInfConfiguration(), new EnvConfiguration() });
server.setHandler(context);
// 启动
server.start();
// 打印dump时的信息
System.out.println(server.dump());
// join当前线程
server.join();
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MvcConfig.class);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", new DispatcherServlet(context));
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
MvcConfig的代码:
@Configuration
@ComponentScan(basePackages = { "com.test.mvc" })
@EnableWebMvc
public class MvcConfig {
}