通过ServletContainerInitializer注册Servlet对象
Servlet3通过SPI的机制允许我们自定义一个ServletContainerInitializer的实现类,Servlet容器会在启动的时候自动调用实现类的onStartup
方法,我们可以在该方法中进行一些Servlet对象的注册。ServletContainerInitializer接口的定义如下:
public interface ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}
在下面的代码中自定义了一个ServletContainerInitializer的实现类,叫MyServletContainerInitialier。在其onStartup方法中我们通过入参ServletContext分别注册了一个Servlet、一个监听器和一个Filter。
public class MyServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
//注册Servlet
javax.servlet.ServletRegistration.Dynamic servletRegistration = ctx.addServlet("hello", HelloServlet.class);
servletRegistration.addMapping("/servlet3/hello");
servletRegistration.setLoadOnStartup(1);
servletRegistration.setAsyncSupported(true);
//注册监听器
ctx.addListener(StartupListener.class);
//注册Filter
javax.servlet.FilterRegistration.Dynamic filterRegistration = ctx.addFilter("hello", HelloFilter.class);
filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/servlet3/*");
}
}
它是基于SPI发现的,这需要我们在classpath下面的META-INF/services下新建一个名为javax.servlet.ServletContainerInitializer
的文件,然后在里面加上我们自定义的ServletContainerIntializer的全路径名称。如果有多个实现类,每一个实现类写一行。
HandlesTypes
在上面的示例中我们在onStartup的实现中完全没有使用第一个参数classes,它是干什么用的呢?Servlet3允许我们在定义自定义的ServletContainerInitializer的时候通过@HandlesTypes
注解指定在自定义的ServletContainerInitializer初始化的时候,也就是调用onStartup时需要自动检测的类型,然后把它们作为onStartup的第一个参数。这在我们搭建框架的时候非常有用,我们可以通过它对外定义一个接口,让有需要通过它来动态注册Servlet对象的人都可以只需要实现我们开放的接口来注册Servlet对象,他们不需要实现完整的ServletContainerInitializer接口,并按照SPI规范在javax.servlet.ServletContainerInitailizer
文件中定义。
下面示例中我们通过@HandlesTypes(WebInitializer.class)
指定了在容器初始化的时候需要自动检测WebInitializer
类型的Class
,然后在onStartup
方法体中利用反射一一实例化WebInitializer
接口实现类,并调用它们的onStartup
方法进行Servlet对象的注册。
@HandlesTypes(WebInitializer.class)
public class MyServletContainerInitializer2 implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> classes, ServletContext ctx)
throws ServletException {
// classes就是自动检测到的类路径下的该初始化类上的@HandlesTypes指定的类,
// 在本示例中就是WebInitializer接口的实现类
if (classes != null && !classes.isEmpty()) {
for (Class<?> initializerClass : classes) {
if (!initializerClass.isInterface()
&& !Modifier.isAbstract(initializerClass.getModifiers())) {
WebInitializer initializer;
try {
initializer = (WebInitializer) initializerClass.newInstance();
initializer.onStartup(ctx);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
public interface WebInitializer {
void onStartup(ServletContext ctx) throws ServletException;
}
(注:本文是基于Servlet3.1所写,由Elim写于2018年6月23日)
相关推荐
此外,它还用于注册监听器、获取其他Servlet或JSP的信息等。 6. **HttpServletRequest和HttpServletResponse接口**:这两个接口分别代表了HTTP请求和响应对象,提供了获取和设置请求头、参数、cookies,以及设置...
Servlet通过`HttpServletRequest`和`HttpServletResponse`对象与客户端进行通信。前者封装了请求数据,后者用于构建响应。你可以通过这些对象获取请求参数、头信息,设置响应状态码、内容类型等。 八、实战演练 在...
4. `ServletContainerInitializer`: 自动注册Servlet和Filter。 通过Servlet、Filter和Listener,开发者可以构建高度定制化的Web应用程序,实现更精细的控制和扩展性。它们共同构成了Java Web应用的基石,帮助...
开发者可以在应用运行时动态地注册Servlet、Filter和Listener,而无需在web.xml中预先配置。`ServletContainerInitializer`接口用于实现这个功能,允许自定义初始化逻辑。 6. **安全增强**: Servlet3.1提供了更...
- 动态注册:通过Java代码使用`ServletContainerInitializer`实现Servlet的动态注册。 3. **Servlet容器**: - Tomcat:深入理解Tomcat作为Servlet容器的工作原理。 - Servlet上下文:掌握`ServletContext`对象...
通过编写实际的Servlet应用,如构建一个简单的CRUD应用,或者实现一个登录注册系统,你可以更好地理解和掌握这些概念。此外,配合阅读提供的"深入学习JavaServlet开发与实例.pdf",结合具体案例分析,将有助于巩固...
这为开发者提供了在容器启动时进行配置或注册Servlet、Filter和Listener的灵活性,而无需传统的web.xml配置文件。 接下来,我们将关注`ServletContext`,这是Servlet容器的核心组件。在Spring注解驱动的开发中,`...
这部分主要涉及到四层架构(表现层、业务逻辑层、数据访问层、持久化层)的应用,以及使用Servlet、JSP、Cookie和Filter处理用户注册、登录、删除、修改和查询等操作。对于中文乱码,需要在Filter中设置正确的字符...
// 注册Servlet工厂 ctx.setInitParameter("jspServletClass", "com.example.MyCustomJspServlet"); } } ``` 在这个例子中,我们使用`setInitParameter`方法将默认的JSPServlet替换为自定义的`...
在Servlet 3.0中,提供了多种配置和注册servlet的方式: * 使用web.xml文件(listing 1) * 使用web-fragment.xml文件(listing 2) * 使用javax.servlet.ServletContainerInitializer(listing 3) * 如果使用...
- **注册监听器和Servlet**:将带有WebApplicationInitializer或ServletContainerInitializer接口的类注册为监听器或Servlet。 - **调用ApplicationReadyEvent**:发布此事件,表示应用已经准备就绪,可以开始处理...
- **`@Bean`注解**:标记在方法上,表示该方法返回的对象将作为bean注册到Spring容器中。 - **`@Configuration`注解**:标记配置类,表明此类包含一个或多个`@Bean`方法。 ##### 2. Bean的作用域 - **`@Scope`注解...
Servlet3 规定,如果在当前项目的 classPath 下,存在 META-INF/services/javax.servlet.ServletContainerInitializer 配置文件,且文件中写了 ServletContainerInitializer 的实现类的全类名,容器启动时实现类的 ...