一、Servlet容器启动时会扫描当前应用中每一个jar包中的在META-INF/services/javax.servlet.ServletContainerInitializer文件(该文件没有后缀名)中配置的ServletContainerInitializer的实现类,javax.servlet.ServletContainerInitializer文件的内容就是ServletContainerInitializer实现类的全类名,启动时会运行这些实现类的onStartUp方法,可以通过@HandlesTypes传入一些感兴趣的类型,在onStartUp方法中做一些操作。一个jar包中只能有一个javax.servlet.ServletContainerInitializer配置文件,一个javax.servlet.ServletContainerInitializer配置文件中只能配置一个ServletContainerInitializer实现类。
ServletContainerInitializer实现类:
@HandlesTypes({HelloServiceInterface.class})
public class MyServletContainerInitializer implements ServletContainerInitializer{
@Override
public void onStartup(Set> set, ServletContext context) throws ServletException {
System.out.println("感兴趣的类:");
for (Class> clazz : set) {
System.out.println(">>>>>>" + clazz);
}
}
}
onStartUp方法的入参:
set是@HandlesTypes中传入的接口或者类的所有子接口或者子类(不包含该接口或该类本身);context是web项目的servlet上下文,一个web项目对应一个ServletContext,通过ServletContext可以来注册web组件,比如第三方的filter组件(由于第三方的组件并不是我们写的,我们无法通过@WebServlet、@WebFilter、@WebListener来标注使其拦截相应的请求,这个时候就需要在ServletContainerInitializer中通过ServletContext来注册了)
javax.servlet.ServletContainerInitializer配置文件内容:
com.bdm.servlet.MyServletContainerInitializer
javax.servlet.ServletContainerInitializer配置文件的目录:
此时在项目启动时可以看到后台日志中打印出:
二、使用ServletContext注册web组件
UserServlet.java:
public class UserServlet extends HttpServlet{
private static final long serialVersionUID = -5343785314009218808L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("tomcat...");
}
}
UserFilter.java:
public class UserFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)
throws IOException, ServletException {
System.out.println("UserFilter...doFilter...");
chain.doFilter(arg0, arg1);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
UserListener.java:只要实现了ServletContextListener接口就可以监听到ServletContext(Servlet容器)的创建和销毁
public class UserListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("UserListener...contextDestroyed...");
}
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("UserListener...contextInitialized...");
}
}
注册web组件:
@HandlesTypes({HelloServiceInterface.class})
public class MyServletContainerInitializer implements ServletContainerInitializer{
@Override
public void onStartup(Set> set, ServletContext context) throws ServletException {
ServletRegistration.Dynamic userServlet = context.addServlet("userServlet", new UserServlet());
userServlet.addMapping("/user");
FilterRegistration.Dynamic filter = context.addFilter("userFilter", UserFilter.class);
filter.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true, "userServlet");
filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
context.addListener(UserListener.class);
}
}
context.addServlet()注册servlet组件,context.addFilter()注册filter组件,这两个组件都需要配置映射路径,其中filter还可以配置拦截哪些servlet;context.addListener()注册listener,listener在tomcat启动时就会调用其中的逻辑;
servlet、filter、listener这些组件的注册必须在tomcat容器启动的时候,有两处可以进行这些组件的注册,一个就是上面的例子(通过ServletContainerInitializer中的ServletContext来注册),还有一个地方可以注册,就是在ServletContextListener的实现类中获取到ServletContext,然后通过ServletContext注册其他的listener、filter、servlet:
@WebListener
public class UserListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("UserListener...contextDestroyed...");
}
@Override
public void contextInitialized(ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
Dynamic addServlet = servletContext.addServlet("userServlet", UserServlet.class);
addServlet.addMapping("/user");
javax.servlet.FilterRegistration.Dynamic addFilter = servletContext.addFilter("userFilter", UserFilter.class);
addFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
}
}
此处的UserLisener需要使用@WebListener注解的方式注册,而不可以在ServletContainerInitializer中注册,不知道什么原因?