使用ServletContainerInitializer动态注册组件

1.背景

在web容器(例如tomcat)启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等。对此servlet规范提供了ServletContainerInitializer来实现这个功能。

每个框架要使用ServletContainerInitializer就必须在对应的jar包的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个ServletContainerInitializer实现类做一些组件内的初始化工作。

1.1 spring-web的实现

如图是spring框架使用ServletContainerInitializer的处理方法:
image

//service下面org.springframework.web.SpringServletContainerInitializer内容是ServletContainerInitializer的实现类:
org.springframework.web.SpringServletContainerInitializer

//点进去SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)//通过@HandlesTypes在onStartup方法执行的时候,把指定类的实现类(包括指定类本身)传递进去
public class SpringServletContainerInitializer implements ServletContainerInitializer {
...
 public void onStartup()
...
}

1.2 动态注册servlet

可以在ServletContainerInitializer里面动态注册servlet(servlet3大组件),只限于容器启动时动态注册,出于安全性考虑无法在运行时动态注册。

@HandlesTypes({ JarWelcomeServlet.class }) 
public class CustomServletContainerInitializer implements 
    ServletContainerInitializer { 
  private static final Log log = LogFactory 
      .getLog(CustomServletContainerInitializer.class); 

  private static final String JAR_HELLO_URL = "/jarhello"; 

  public void onStartup(Set<Class<?>> c, ServletContext servletContext) 
      throws ServletException { 
    log.info("CustomServletContainerInitializer is loaded here..."); 
    
    log.info("now ready to add servlet : " + JarWelcomeServlet.class.getName()); 
    
    ServletRegistration.Dynamic servlet = servletContext.addServlet( 
        JarWelcomeServlet.class.getSimpleName(), 
        JarWelcomeServlet.class); 
    servlet.addMapping(JAR_HELLO_URL); 

    log.info("now ready to add filter : " + JarWelcomeFilter.class.getName()); 
    FilterRegistration.Dynamic filter = servletContext.addFilter( 
        JarWelcomeFilter.class.getSimpleName(), JarWelcomeFilter.class); 

    EnumSet<DispatcherType> dispatcherTypes = EnumSet 
        .allOf(DispatcherType.class); 
    dispatcherTypes.add(DispatcherType.REQUEST); 
    dispatcherTypes.add(DispatcherType.FORWARD); 

    filter.addMappingForUrlPatterns(dispatcherTypes, true, JAR_HELLO_URL); 

    log.info("now ready to add listener : " + JarWelcomeListener.class.getName()); 
    servletContext.addListener(JarWelcomeListener.class); 
  } 
}

posted on 2018-12-12 00:40  lukelin1989  阅读(577)  评论(0)    收藏  举报

导航