3.11.4. Servlet 和过滤器的注册

要使用应用程序组件中定义的 servlet 和安全过滤器,需要在应用程序中注册它们。servlet 通常在web.xml配置文件中注册,但是,这种配置不会传递到使用此应用程序组件的应用程序中。

ServletRegistrationManager bean 能够使用正确的类加载器动态注册 servlet 和过滤器,并允许使用类似于AppContext的静态类。它还保证对所有部署选项都能正确工作。

ServletRegistrationManager 有两个方法:

  1. createServlet() - 创建给定 servlet 类的 servlet。它使用从应用程序上下文对象获取的正确的 ClassLoader 加载 servlet 类。这意味着新的 servlet 将能够使用平台的一些静态类,例如,AppContextMessages bean。

  2. createFilter() - 以相同的方式创建过滤器.

要使用这个 bean,建议在应用程序组件中创建一个托管的初始化 bean。这个 bean 应该使用 @Component 注解,并包含监听应用程序上下文初始化和销毁事件(ServletContextInitializedEventServletContextDestroyedEvent)的监听器。

初始化 bean 的一个示例:

@Component
public class WebInitializer {

    @Inject
    private ServletRegistrationManager servletRegistrationManager;

    @EventListener
    public void initializeHttpServlet(ServletContextInitializedEvent e) {
        Servlet myServlet = servletRegistrationManager.createServlet(e.getApplicationContext(), "com.demo.comp.MyHttpServlet");

        e.getSource().addServlet("my_servlet", myServlet)
                .addMapping("/myservlet/");
    }
}

这里的 WebInitializer 类只有一个事件监听器,用于从应用程序组件中给项目应用程序注册 HTTP servlet。

createServlet() 方法使用从 ServletContextInitializedEvent 获取的应用程序上下文和 HTTP servlet 的完全限定名。然后使用名称(my_servlet)注册 servlet 并定义 HTTP-mapping(/myservlet/)。现在,如果将此应用程序组件添加到应用程序中,将在初始化 servlet 和应用程序上下文后立即注册 MyHttpServlet

相关更复杂的示例,请参阅在应用程序组件中注册 DispatcherServlet部分。

单个 WAR 包部署模式下的 Servlet 注册

要在单 WAR 部署中正确加载自定义过滤器和 servlet,请按照以下步骤操作:

  1. 创建一个继承 javax.servlet.ServletContextListener 的类。这个类将负责 servlet 和过滤器的创建:

    public class CustomWebListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            ServletContext servletContext = servletContextEvent.getServletContext();
            registerServlet(servletContext);
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    
        protected void registerServlet(ServletContext servletContext) {
            Servlet testServlet = new TestServlet();
            ServletRegistration.Dynamic servletReg = servletContext.addServlet("test_servlet", cubaServlet);
            servletReg.setLoadOnStartup(0);
            servletReg.setAsyncSupported(true);
            servletReg.addMapping("/testServlet");
        }
    }
  2. single-war-web.xml 文件中添加一个引用所创建类的新参数 context-param

    <context-param>
        <param-name>webServletContextListener</param-name>
        <param-value>com.company.CustomWebListener</param-value>
    </context-param>