Loading

编程式动态注册Servlet组件

有时我们需要动态注册Servlet组件的能力,而非使用xml与诸如@WebFilter这种声明式的方式来注册Servlet组件,尤其是使用框架开发时。

Servlet3.0中向ServletContext中添加了一些方法用于动态添加Servlet组件,这些方法必须在应用程序初始化时被调用,如在实现了ServletContextListener接口的类的contexInitialized中或实现了ServletContainerInitializer接口的类的onStartup中。由于刚刚学过ServletContextListener,所以本例中,我们使用另一种没见过的,ServletContainerInitializer的方式来实验。

创建ServletContainerInitializer

这个Initializer会在容器初始化时被调用,使用SPI方式完成初始化。

创建MyServletContainerInitializer类,实现ServletContainerInitializer接口:

public class MyServletContainerInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        System.out.println("onStartup");
    }
}

resources/META-INF/services下,创建名为javax.servlet.ServletContainerInitializer的文件,文件中填写你实现类的全限定名:

top.yudoge.webreview2.MyServletContainerInitializer

开启容器,运行,Initializer已经生效:

img

编程式添加、配置Servlet

现在在onStartup方法中,我们有了ServletContext的实例,其中包含这样一个方法:

/**
* 添加具有给定的名字和类的servlet到ServletContext中
* 添加的servlet可以通过返回的ServletRegistration对象被进一步配置
*/
public ServletRegistration.Dynamic addServlet(
    String servletName, String className);

该方法的第一个参数是Servlet名,第二个参数是要添加的Servlet类的全限定名。方法返回一个ServletRegistration.Dynamic,用于对注册的Servlet进行配置。

这个ServletRegistration.Dynamic在SpringMVC中想要注册一个Filter时非常常见,我还以为是SpringMVC中的类,结果是servlet提供的功能。

下面使用这个方法动态注册一个Servlet:

@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
    ServletRegistration.Dynamic sr = ctx.addServlet("instructorServlet", InstructorsServlet.class.getName());
    sr.addMapping("/instructors");
    sr.setLoadOnStartup(1);
    sr.setInitParameter("name", "value");
}

访问这个Servlet:

img

你还可以使用如下重载方法来注册Servlet:

public ServletRegistration.Dynamic addServlet(
    String servletName, Servlet servlet);

public ServletRegistration.Dynamic addServlet(String servletName,
    Class <? extends Servlet> servletClass);

区别就是Servlet类的类加载器有可能不同,使用后两种方法时,Servlet的类应该已经被加载过了,第一种方法则不一定。

其它一些方法

  • 根据给定类创建Servlet
    <T extends Servlet> T createServlet(Class<T> clazz)
    
  • 获取ServletRegistration
     ServletRegistration getServletRegistration(String servletName)
    
  • 获取所有ServletRegistration
    Map<String, <? extends ServletRegistration> getServletRegistrations()
    

关于Filter和Listener的编程式注册,和Servlet大同小异

推荐阅读:Spring实战 五 Web中的Spring - 配置DispatcherServlet

posted @ 2022-07-21 10:40  yudoge  阅读(137)  评论(0编辑  收藏  举报