在之前典型的Java Web程序中,部署描述符web.xml是必不可少的,在这里我们需要配置各种组件,包括Servlet、Filter和Listener等,如果使用过SpringMVC的话,应该会对在web.xml中配置org.springframework.web.servlet.DispatcherServlet十分熟悉。但是对于所有的配置文件都有的一个通病就是只有在程序部署的时候,一些配置项问题才能被发现,而不能在程序编译开发阶段就发现。所以如果通过编程的方法来设置配置项则是一个最好的选择,我们完全可以抛弃web.xml这个部署描述符,而是换用从Servlet 3.0中提出的一个接口javax.servlet.ServletContainerInitializer来完成Servlet容器的初始化,该接口的作用是当Web应用启动时,通知一些实现类来执行一些要求的Servlet、Filter和Listener等的编程注册。
一、接口说明
ServletContainerInitializer接口细节:
其中只有一个方法
onStartup(...),在执行任何ServletContext监听器之前,由Servlet容器调用这个方法,该方法的主要作用是注册Web对象;实现
ServletContainerInitializer的类必须使用@HandleTypes注解进行标注,以便声明onStartup(...)可以处理这个类的实例,所有该类、包括它的子类都会被传递给其中的Set<Class<?>> c字段,如果没有这个注解,或者在该注解中使用的类不存在或没有相应的子类,则会传递给该参数一个null值;这个接口被设计在
jar文件中使用,而无法直接在war包中直接使用,而是通过在jar中完成定义,然后将jar包作为Java Web的依赖包,该接口的实现类会通过Java的SPI的注册查询机制被发现;如果要使用这个类,需要一个元数据文件来说明如何定位该接口的实现类,该文本文件在META-INF/services文件夹下,这个文本文件的名称为
javax.servlet.ServletContainerInitializer,其中的内容是该接口的实现类的全限定名;
二、编程实现
1、构建jar依赖包
首先搭建依赖包工程,这里使用Maven管理工程,依赖项只需要一个,如下:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
Maven项目目录如下:
其中
ServletContainerInitializer的实现类为com.demo.CustomServletContainerInitializer,为了在jar中加入META-INF/services文件夹,只需要将该文件夹直接放到maven的资源文件夹resources下即可,在打包的时候就会在jar中实现该文件夹,并包括之前的文件;可以看出
META-INF/services文件夹中的文本文件名为javax.servlet.ServletContainerInitializer,其中的内容为com.demo.CustomServletContainerInitializer,为该接口的实现类;在
CustomServletContainerInitializer中的实现如下:@HandlesTypes({HttpServlet.class}) public class CustomServletContainerInitializer implements ServletContainerInitializer { public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException { for(Class<?> clazz: c){ System.out.println(clazz.getName()); } } }该实现类在Java Web应用启动时,会调用该方法,传递
HttpServlet类以及其子类。
2、构建Java Web程序
Java Web程序的工程目录如下:
在工程中必须有
webapp这个目录,如果没有则会导致异常java.lang.IllegalArgumentException: Document base ... src\main\webapp does not exist or is not a readable directory;这里我们定义一个
Servlet类TestServlet,通过使用注解@javax.servlet.annotation.WebServlet来标识这个Servlet,代码如下:@WebServlet(urlPatterns = "/testServlet", name = "testServlet") public class TestServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Writer writer = resp.getWriter(); writer.write("do get"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Writer writer = resp.getWriter(); writer.write("do post"); } }这个注解是在应用启动的时候被容器处理,并且都对应的servlet也可以通过相应的URL来访问;
在程序启动的过程中,会发现传递进来很多的servlet子类和Filter的实现类,如下:
其中也包括我们自定义的一个TestServlet。
相关文章:
本文介绍了在Java Web开发中如何摆脱web.xml,利用Servlet 3.0的ServletContainerInitializer接口进行容器初始化。详细讲解了接口说明和编程实现,包括创建依赖包,构建Java Web程序,以及使用注解进行Servlet和Filter的编程注册。
1万+

被折叠的 条评论
为什么被折叠?



