本文介绍下SpringBoot中如何对这几者的注册与使用

SpringBoot有两种方式注册Servlet、Filter、Listener

1、代码注册:使用 ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean进行注册;

2、 在 SpringBootApplication上添加@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册

Servlet

servlet是一个用户请求。

servlet的匹配规则:从精确到模糊,匹配到之后不会管其他

比如:servlet1的url-pattern 是/test,serlet2的url-pattern是/*,访问的url为 http://localhost:8080/test ,容器就会先进行全路径匹配,发现正好被servlet1精确匹配,就不会去管servlet2

1、通过@ServletComponentScan自动扫描注册

①在springboot入口程序除添加 @ServletComponentScan

1
2
3
4
5
6
7
@SpringBootApplication
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

②使用@WebServlet自定义Servlet,配置请求路径为/demo/servlet1

可配置参数如下

可配置参数

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@WebServlet(name = "myServlet1",urlPatterns = "/demo/servlet1",description = "自定义Servlet1")
public class MyServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

System.out.println("-----------MyServlet1---------doGet-------");
resp.getWriter().println("myServlet1 request");
//super.doGet(req, resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("-----------MyServlet1---------doPost-------");
super.doPost(req, resp);
}
}

请求结果:

请求结果

2、通过@ServletRegistrationBean注解注册

① 自定义Servler,此时只需继承HttpServlet即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyServlet2 extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("-----------MyServlet2---------doGet-------");
resp.getWriter().println("myServlet2 request");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("-----------MyServlet2---------doPost-------");
super.doPost(req, resp);
}
}

② 使用 ServletRegistrationBean注入bean

注意:添加@Configuration是定义配置类,将ServletRegistrationBean注入容器即可实现Servlet

1
2
3
4
5
6
7
@Configuration
public class RegistrationConfiguration {
@Bean
public ServletRegistrationBean myServlet2(){
return new ServletRegistrationBean(new MyServlet2(),"/demo/servlet2");
}
}

请求结果:

请求结果

Filter

Filter:过滤器,对请求进行过滤,可对请求、响应进行修改。

完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

多个过滤器组成过滤器调用链,按设置顺序执行,形成Filter链。

Filter的作用:

  1. 在请求到达Servlet之前,拦截客户传来的请求
  2. 可以对请求进行检查、判断,亦可以进行修改
  3. 在请求到达客户端之前,拦截响应
  4. 可以对响应进行检查、判断、修改

1、通过@ServletComponentScan自动扫描注册

① 在springboot入口程序除添加 @ServletComponentScan

② 使用@WebFilter 配置处理全部url的Filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@WebFilter(filterName = "myFilter",urlPatterns = "/demo/servlet1")
public class MyFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println(">>>>>>myFilter init ……");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println(">>>>>>执行过滤操作");
chain.doFilter(request, response);
}

@Override
public void destroy() {
System.out.println(">>>>>>myFilter destroy ……");
}
}

运行结果:启动时会执行init()方法,拦截到对应请求时执行doFilter(),web应用关闭时执行destroy()方法

init

doFilter()方法是过滤器的和核心方法,实现该方法就可以实现对用户请求进行预处理,也可以实现对服务器响应进行处理,他们的分界线为是否调用chain.doFilter(),执行该方法之前,对用户请求进行预处理,执行该方法之后,对服务器响应进行后处理

doFilter

destroy:

destroy

2、使用FilterRegistrationBean

  1. 使用@Bean注入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Configuration
    public class RegistrationConfiguration {
    @Bean
    public FilterRegistrationBean myFilter2(){
    FilterRegistrationBean<MyFilter2> filterRegistrationBean = new FilterRegistrationBean<>();
    filterRegistrationBean.setFilter(new MyFilter2());
    filterRegistrationBean.addUrlPatterns("/hello","/test","/demo/servlet2");
    return filterRegistrationBean;
    }
    }
  2. MyFilter2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    System.out.println("MyFilter2 init....");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    System.out.println("MyFilter2 doFilter....former...");
    chain.doFilter(request, response);
    System.out.println("MyFilter2 doFilter....after...");
    }
    @Override
    public void destroy() {
    System.out.println("myFilter destroy....");
    }
    }

    请求结果就不贴图了,测试结果与MyFilter类似。

Listener

首先Listener是只能是以下几个接口的实现类,其中包括4个 EventListeners( ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener)和2个 LifecycleListeners(ServletContextListener、HttpSessionListener);

  • ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。
  • ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。
  • HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发session Created(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。
  • HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。

1、通过@ServletComponentScan自动扫描注册

  1. 使用ServletListenerRegistrationBean注入bean

  2. 自定义Listener

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @WebListener
    public class MyListener1 implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
    System.out.println("MyListener1 contextInitialized.....");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    System.out.println("MyListener1 contextDestroyed....");
    }
    }

    运行结果:

    MyListener1

2、通过@ServletListenerRegistrationBean 注册

  1. 手动注册bean

    1
    2
    3
    4
    5
    6
    7
    @Configuration
    public class RegistrationConfiguration {
    @Bean
    public ServletListenerRegistrationBean myListener2(){
    return new ServletListenerRegistrationBean(new MyListener2());
    }
    }
  2. 自定义Listener

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class MyListener2 implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
    System.out.println("MyListener2 contextInitialized.....");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    System.out.println("MyListener2 contextDestroyed....");
    }
    }

    结果:

    结果

以上可得出三的运行顺序:Listener>Filter>Servlet

Intercepter

拦截器只会处理DispatcherServlet处理的url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println(">>>>MyInterceptor preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println(">>>>MyInterceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println(">>>>MyInterceptor afterCompletion");
}
}

注册拦截器

1
2
3
4
5
6
7
8
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}

浏览器访问 http://localhost:8080/demo/servlet1 此时MyInterceptor不会拦截,因为被自定义Servlet处理。

访问其他未被自定义Servlet匹配的url,可以看到MyInterceptor输出。

Intercepter生命周期详见: https://www.cnblogs.com/junzi2099/p/8022058.html