SpringBoot中的Servlet-Filter-Listener
Java Web三大组件
传统Java web项目
- 最常用的三大组件有
Servlet
、Filter
和Listener
。使用这些组件时需要在项目的web.xml
文件中进行配置,或者使用相应的注解进行标注。
Spring Boot项目
- 默认没有
web.xml
文件,同时默认情况下Spring Boot项目
不能自动识别到这三个组件的相关注解。可以使用Spring Bean
、RegistrationBean
、注解扫描
的方式注册Java Web
三大组件。
在Spring Boot项目中由于默认大于配置,会自动将Spring容器中的
Servlet
、Filter
、Listener
实例注册为Web服务器中对应的组件。因此,可以将自定义的Java Web三大组件作为Bean添加到Spring容器中,以实现组件的注册。
Servlet测试
- SecondServlet
/**
* @Title: SecondServlet
* @Author David
* @Package com.work.spring.springbootwork.Servlet
* @Date 2024/9/14 下午4:37
* @description:
*/
public class SecondServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Hello SecondServlet!");
resp.getWriter().write("Hello SecondServlet!");
}
}
- FirstServlet
/**
* @Title: FirstServlet
* @Author David
* @Package com.work.spring.springbootwork.Servlet
* @Date 2024/9/14 下午4:34
* @description:
*/
public class FirstServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("Hello FirstServlet!");
response.getWriter().write("Hello FirstServlet!");
}
}
Filter测试
- MyFilter
/**
* @Title: MyFilter
* @Author David
* @Package com.work.spring.springbootwork.filter
* @Date 2024/9/14 下午4:39
*/
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("处理请求前的处理");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("处理请求后的处理");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Listener测试
- MyListener
/**
* @Title: MyListener
* @Author David
* @Package com.work.spring.springbootwork.listener
* @Date 2024/9/14 下午4:43s
*/
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
System.out.println("----Web 应用初始化完成----");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("----Web 应用销毁之前----");
}
}
将Servlet、Filter和Listener通过@Configuration加入Bean
- WebConfigure
:::note 所有文件通过@Configuration
+ @Bean
注册进入Bean容器
不用测试Servlet用Bean注入会有生命周期的问题得使用RegistrationBean
:::
/**
* @Title: WebConfigure
* @Author David
* @Package com.work.spring.springbootwork.config
* @Date 2024/9/14 下午4:46
*/
@Configuration
public class WebConfigure {
@Bean("firstServlet")
public FirstServlet firstServlet() {
return new FirstServlet();
}
@Bean("secondServlet")
public SecondServlet secondServlet() {
return new SecondServlet();
}
@Bean
public MyFilter myFilter() {
return new MyFilter();
}
@Bean
public MyListener myListener() {
return new MyListener();
}
}
测试成功截图
- FirstServlet
FirstServlet测试成功截图
- SecondServlet
SecondServlet测试成功截图
- MyFilter
MyFilter测试成功截图
- Listener
Listener测试成功截图
使用Spring Bean注册Servlet时,需要自定义两个及以上的Servlet,Servlet对应的映射地址为“Bean名称+/”。Filter的映射地址默认为“/*”。
RegistrationBean注册三大组件
- 使用Spring Bean注册Java Web三大组件时,如果容器中只有一个自定义Servlet,则
无法使用Bean的名称作为映射路径
,而Filter默认只使用“*”的映射地址。为解决此问题Spring Boot提供了更为灵活的注册方法,可以在配置类中使用 RegistrationBean来注册原生Web组件。 - RegistrationBean是个抽象类,SpringBoot提供了三个RegistrationBean的实现类:
ServletRegistrationBean
、FilterRegistrationBean
、ServletListenerRegistrationBean
,这三个类分别用来注册Servlet、Filter和Listener,通过这三个类开发者可以获得自定义映射路径等更多的控制权。
RegistrationBean常用方法:
1. ServletRegistrationBean
ServletRegistrationBean
用于将自定义的 Servlet
注册到 Spring Boot 的嵌入式容器(如 Tomcat、Jetty)中,并进行一些初始化配置。
ServletRegistrationBean(T servlet, String... urlMappings)
- 用于初始化
Servlet
,并设置 URL 映射。 - 参数:
servlet
: 需要注册的Servlet
实例。urlMappings
: 该Servlet
映射的 URL 模式(例如"/myServlet/*"
)。
- 用于初始化
/myServlet
是通过ServletRegistrationBean
的构造方法传递的 URL 映射路径,它实际上就是通过addUrlMappings
方法设置的地址,用于定义该Servlet
处理请求的路径。
setLoadOnStartup(int loadOnStartup)
设置
Servlet
的加载优先级。值越小优先级越高,默认值是-1
。示例:
registrationBean.setLoadOnStartup(1);
加载时机:
loadOnStartup
值决定了Servlet
的加载时机。默认值为 -1,意味着 Servlet 会在收到首次请求时才被加载。如果设置为正整数,Servlet 会在服务器启动时立即加载。优先级:正整数值还表示加载的优先级,值越小优先级越高。例如,0 表示最高优先级,1 表示次高优先级,以此类推。负数值(如 -1)意味着懒加载,也就是直到有请求到达该 Servlet 时才加载。
setName(String name)
设置
Servlet
的名称。示例:
registrationBean.setName("MyServlet");
而是这个
Servlet
的逻辑名称,主要用于在日志、监控工具或者容器管理中对Servlet
进行标识
addUrlMappings(String... urlMappings)
添加 URL 映射,指定
Servlet
将处理哪些请求路径。示例:
registrationBean.addUrlMappings("/customServlet/*");
添加
URL
映射,指定该 Servlet 处理 "/customServlet/*" 路径的请求
setAsyncSupported(boolean isAsyncSupported)
设置是否支持异步处理。
示例:
registrationBean.setAsyncSupported(true);
异步处理允许
Servlet
在处理请求时不阻塞当前线程。当设置setAsyncSupported(true)
时,Servlet
就可以使用异步处理机制,将任务交给另一个线程来处理,而当前线程可以立即释放,处理其他请求
setInitParameters(Map<String, String> initParameters)
设置
Servlet
初始化参数。示例:
Map<String, String> params = new HashMap<>(); params.put("config", "value"); registrationBean.setInitParameters(params);
初始化参数:这些参数在 Servlet 初始化阶段传递,并且只能在 Servlet 的生命周期内使用,通常通过 ServletConfig.getInitParameter() 方法来访问。
用途:初始化参数通常用于配置 Servlet 的一些基本信息,比如数据库连接信息、特定行为开关、静态文件路径等。
setEnabled(boolean enabled)
启用或禁用
Servlet
,默认是启用的。示例:
registrationBean.setEnabled(false);
这对于某些场景很有用,比如在开发或测试环境中,临时禁用某些 Servlet,而不需要修改其他配置。
2. FilterRegistrationBean
FilterRegistrationBean
用于将自定义的 Filter
注册到 Spring Boot 的嵌入式容器中,通常用于拦截和处理 HTTP 请求。
FilterRegistrationBean(T filter)
构造器,用于注册
Filter
。参数:
filter
: 需要注册的Filter
实例。
示例
// T filter是泛类的意思 public FilterRegistrationBean<MyFilter> myFilterBean(){}
addUrlPatterns(String... urlPatterns)
添加过滤器要处理的 URL 模式。
示例:
registrationBean.addUrlPatterns("/api/*");
setOrder(int order)
设置过滤器的执行顺序,数字越小优先级越高。
示例:
registrationBean.setOrder(1); // 优先级高
使用场景为,有多个filter过滤器的时候可以对请求进行多次处理
setServletNames(String... servletNames)
为指定的
Servlet
配置过滤器。这个方法允许你将过滤器应用于特定的Servlet
。示例:
registrationBean.setServletNames("MyServlet");
是一个逻辑名称,方便日志观察
setEnabled(boolean enabled)
启用或禁用
Filter
,默认是启用的。示例:
registrationBean.setEnabled(false); // 禁用过滤器
通过boolean值去控制拦截器是否生效,可以用配置文件动态的配置,适合分布式系统使用
setDispatcherTypes(DispatcherType... dispatcherTypes)
设置过滤器处理的调度类型,如
REQUEST
、FORWARD
、INCLUDE
、ERROR
等。示例:
registrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD);
setDispatcherTypes 方法指定了过滤器在哪些调度类型下生效。你可以通过这个方法精确控制过滤器在处理哪些类型的请求时触发。
REQUEST:表示处理客户端发来的请求。这个是最常见的调度类型,通常处理所有直接的 HTTP 请求。
FORWARD:当一个 Servlet 或 JSP 通过 RequestDispatcher.forward() 将请求转发给另一个资源时,这个调度类型会被触发。
INCLUDE:当一个 Servlet 或 JSP 通过 RequestDispatcher.include() 将另一个资源的输出包含在自己的响应中时,触发该类型。
ERROR:当请求发生错误并进入错误处理阶段时,这个类型会被触发。
ASYNC:与异步处理相关的调度类型。
setInitParameters(Map<String, String> initParameters)
设置过滤器的初始化参数。
示例:
Map<String, String> params = new HashMap<>(); params.put("encoding", "UTF-8"); registrationBean.setInitParameters(params);
你可以让过滤器的配置更加灵活。例如,你可以在不同环境中为同一个过滤器提供不同的配置参数,而不需要修改代码
filterConfig.getInitParameter("encoding")
获取参数
3. ServletListenerRegistrationBean
ServletListenerRegistrationBean
用于将 ServletContextListener
或其他 Listener
注册到 Spring Boot 的容器中,用来监听 Servlet 容器的生命周期或某些特定事件。
ServletListenerRegistrationBean(T listener)
构造器,用于注册
Listener
。参数:
listener
: 需要注册的Listener
实例。
示例:
ServletListenerRegistrationBean<MyListener> listenerBean = new ServletListenerRegistrationBean<>(new MyListener());
setListener(T listener)
设置监听器实例。
示例:
listenerRegistrationBean.setListener(new MyListener());
setEnabled(boolean enabled)
启用或禁用
Listener
,默认是启用的。示例:
listenerRegistrationBean.setEnabled(true);
setOrder(int order)
设置监听器的优先级,类似于
Filter
,数字越小优先级越高。示例:
listenerRegistrationBean.setOrder(1);
方法调用的常见使用场景
ServletRegistrationBean
:- 使用场景:注册自定义
Servlet
,例如动态生成内容的Servlet
。 - 常见配置:
addUrlMappings
、setLoadOnStartup
、setAsyncSupported
。
- 使用场景:注册自定义
FilterRegistrationBean
:- 使用场景:拦截和处理 HTTP 请求,如安全过滤、日志过滤、字符编码设置等。
- 常见配置:
addUrlPatterns
、setOrder
、setInitParameters
。
ServletListenerRegistrationBean
:- 使用场景:监听 Web 应用程序生命周期事件,例如应用启动或关闭时执行一些任务。
- 常见配置:
setListener
、setOrder
。
修改Sverlet
- 修改WebConfigure内容
/**
* @Title: WebConfigure
* @Author David
* @Package com.work.spring.springbootwork.config
* @Date 2024/9/14 下午4:46
*/
@Configuration
public class WebConfigure {
@Bean
public FilterRegistrationBean<MyFilter> myFilterBean() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter());
registrationBean.addUrlPatterns("/*"); // 设置过滤的 URL 模式
registrationBean.setOrder(1); // 过滤器的执行顺序,数字越小优先级越高
return registrationBean;
}
@Bean
public ServletListenerRegistrationBean<MyListener> myListenerBean() {
ServletListenerRegistrationBean<MyListener> listenerRegBean = new ServletListenerRegistrationBean<>();
listenerRegBean.setListener(new MyListener());
return listenerRegBean;
}
@Bean("FirstServlet")
public ServletRegistrationBean<FirstServlet> firstServlet() {
ServletRegistrationBean<FirstServlet> bean = new ServletRegistrationBean<>(new FirstServlet(), "/firstServlet");
bean.setName("FirstServlet");
bean.setLoadOnStartup(1); // 设置优先级
return bean;
}
}
@ServletComponentScan注解扫描
- Servlet测试
@WebServlet(name = "FirstServlet", urlPatterns = "/firstServlet/*")
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("Hello FirstServlet!");
response.getWriter().write("Hello FirstServlet!");
}
}
- Listener测试
/**
* @Title: MyListener
* @Author David
* @Package com.work.spring.springbootwork.listener
* @Date 2024/9/14 下午4:43s
*/
@WebListener
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
System.out.println("----Web 应用初始化完成----");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("----Web 应用销毁之前----");
}
}
- Filter测试
/**
* @Title: MyFilter
* @Author David
* @Package com.work.spring.springbootwork.filter
* @Date 2024/9/14 下午4:39
*/
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("处理请求前的处理");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("处理请求后的处理");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
- 启动类添加@ServletComponentScan
@SpringBootApplication
@ImportResource("classpath:beans.xml")
@ServletComponentScan
public class SpringBootWorkApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootWorkApplication.class, args);
}
}