写在前面:

使用Spring-Boot时,嵌入式Servlet容器可以通过扫描注解(@ServletComponentScan)的方式注册Servlet、Filter和Servlet规范的所有监听器(如HttpSessionListener监听器)。

Spring boot 的主 Servlet 为 DispatcherServlet,其默认的url-pattern为“/”。一般情况系统默认的Servlet就够用了,如果需要自定义Servlet,可以继承系统抽象类HttpServlet,重写方法来实现自己的Servlet。关于Servlet、过滤器、拦截器、监听器可以参考:(转)servlet、filter、listener、interceptor之间的区别和联系

Spring-Boot有两种方法注册Servlet、Filter和Listener :

1、代码注册:通过ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制。

2、在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

一、Servlet

Servlet匹配规则:匹配的优先级是从精确到模糊,复合条件的Servlet并不会都执行。

1、通过@ServletComponentScan自动扫描

a、springboot的启动入口添加注解:@ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class ApplicationMain {
public static void main(String[] args) {
SpringApplication.run(ApplicationMain.class, args);
}
}

b、@WebServlet 自定义Servlet,配置处理请求路径 /demo/myServlet

@WebServlet(name = "myServletDemo1",urlPatterns = "/demo/myServlet",description = "自定义的servlet")
public class MyServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("==========myServletDemo Get Method=========="); resp.getWriter().println("my myServletDemo1 process request");
super.doGet(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("==========myServletDemo1 POST Method==========");
super.doPost(req, resp);
}
}

2、使用@ServletRegistrationBean注解

a、@ServletRegistrationBean注入自定义的Servlet,配置处理的路径为 /demo/servletDemo2

@Configuration
public class ServletConfiguration {
/**
* 代码注入
*/
@Bean
public ServletRegistrationBean myServletDemo() {
return new ServletRegistrationBean(new MyServletDemo2(), "/demo/servletDemo2");
}
}

b、自定义的Servlet

public class MyServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("==========myServletDemo2 Get Method=========="); resp.getWriter().println("my myServletDemo2 process request");
super.doGet(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("==========myServletDemo2 POST Method==========");
super.doPost(req, resp);
}
}

二、Filter

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

Filter有如下几个用处。

  • 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
  • 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
  • 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
  • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

多个FIlter可以组成过滤器调用链,按设置的顺序逐一进行处理,形成Filter调用链。

1、通过@ServletComponentScan自动扫描

a、springboot的启动入口添加注解:@ServletComponentScan;

b、@WebFilter 配置处理全部url的Filter

@WebFilter(filterName = "myFilter",urlPatterns = "/*")
public class MyFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println(">>>>>>myFilter init ……");
} public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(">>>>>>执行过滤操作");
filterChain.doFilter(servletRequest, servletResponse);
} public void destroy() {
System.out.println(">>>>>>myFilter destroy ……");
}
}

* doFilter()方法是过滤器的核心方法,实现该方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理——它们的分界线为是否调用了filterChain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。

2、通过@FilterRegistrationBean注册

a、@Bean注入自定义的Filter

@Configuration
public class ServletConfiguration {
@Bean
public FilterRegistrationBean myFilterDemo(){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter2());
registration.addUrlPatterns("/demo/myFilter2");
registration.addInitParameter("paramName", "paramValue");
registration.setName("myFilter2");
registration.setOrder(2);//指定filter的顺序
return registration;
}
}

b、自定义的Filter

public class MyFilter2 implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("======MyFilter2 init ……");
} public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("======MyFilter2执行过滤操作");
filterChain.doFilter(servletRequest, servletResponse);
} public void destroy() {
System.out.println("======MyFilter2 destroy ……");
}
}

三、Listener

目前 Servlet 中提供了 6 种两类事件的观察者接口,它们分别是: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自动扫描

a、ServletListenerRegistrationBean 注入自定义的Listener;

b、自定义的Listener

@WebListener
public class MyLisener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("MyLisener contextInitialized method");
} public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("MyLisener contextDestroyed method");
}
}

2、通过@ServletListenerRegistrationBean 注册

a、@Bean注入自定义的Listener;

@Configuration
public class ServletConfiguration {
@Bean
public ServletListenerRegistrationBean myListener(){
return new ServletListenerRegistrationBean(new MyLisener());
}
}

b、自定义的Listener

public class MyLisener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("MyLisener contextInitialized method");
} public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("MyLisener contextDestroyed method");
}

四、验证servlet、filter、listener的顺序

a、使用MyServletDemo2、MyFilter2、MyFilter3、MyLisener做测试;

b、设置servlet处理url格式为 /demo/*;设置MyFilter2顺序为2;MyFilter3的顺序为3;

@Configuration
public class ServletConfiguration {
/**代码注入*/
@Bean
public ServletRegistrationBean myServletDemo(){
return new ServletRegistrationBean(new MyServletDemo2(),"/demo/*");
} @Bean
public FilterRegistrationBean myFilterDemo(){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter2());
registration.addUrlPatterns("/demo/myFilter");
registration.addInitParameter("paramName", "paramValue");
registration.setName("myFilter2");
registration.setOrder(2);//指定filter的顺序
return registration;
} @Bean
public FilterRegistrationBean myFilterDemo2(){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter3());
registration.addUrlPatterns("/demo/*");
registration.addInitParameter("paramName", "paramValue");
registration.setName("myFilter3");
registration.setOrder(1);
return registration;
} @Bean
public ServletListenerRegistrationBean myListener(){
return new ServletListenerRegistrationBean(new MyLisener());
}
}

c、启动项目后输出:(FIlter2先执行init,因为@Ben在前)

MyLisener contextInitialized method
======MyFilter2 init ……
======MyFilter3 init ……

d、浏览器输入地址地址:http://localhost:8080/demo/myFilter,输出:

======MyFilter3执行过滤操作
======MyFilter2执行过滤操作
>>>>>>>>>>test Get Method==========

可以看出:

  1. Filter3比Filter2先执行;
  2. Filter可以匹配上的url都会执行,并且按顺序执行(Filter的调用链);
  3. Filter比servlet先执行。
  4. servlet先按具体匹配,然后模糊匹配,并且只能有一个servlet匹配上,没有servlet调用链。

执行顺序是:Listener》Filter》Servlet

五、ApplicationListener自定义侦听器类

参考:http://blog.csdn.net/liaokailin/article/details/48186331

六、Interceptor

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

a、自定义拦截器

public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println(">>>>MyInterceptor preHandle");
return true;
} public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println(">>>>MyInterceptor postHandle"); } public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println(">>>>MyInterceptor afterCompletion"); }
}

b、注册拦截器

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}

c、拦截器验证

输入地址:http://localhost:8080/home/test

>>>>MyInterceptor preHandle
>>>>MyInterceptor postHandle
>>>>MyInterceptor afterCompletion

输入地址:http://localhost:8080/demo/myFilter (自定义的Servlet处理了请求,此时拦截器不处理)

拦截器不处理。

Java的Servlet、Filter、Interceptor、Listener的更多相关文章

  1. Java学习之Filter与Listener

    0x00前言 web中的Filiter:当客户端访问服务端资源的时候,过率器可以把请求拦截下来,完成一些特殊的功能 完成的操作一般都是通用的作用:列如登录验证. web中的Listener一般用于加载 ...

  2. SpringBoot整合WEB开发--(九)整合Servlet,Filter,Listener

    简介: 如果需要整合第三方框架时,可能还是不得不使用Servlet,Filter,Listener,Springboot中也有提供支持. @WebServlet("/my") pu ...

  3. servlet/filter/listener/interceptor区别与联系

    转自:http://www.cnblogs.com/doit8791/p/4209442.html servlet.filter.listener是配置到web.xml中(web.xml 的加载顺序是 ...

  4. Servlet、Filter、Listener、Interceptor

    首先,JSP/Servlet规范中定义了Servlet.Filter.Listener这三种角色,并没有定义Interceptor这个角 色,Interceptor是某些MVC框架中的角色,比如Str ...

  5. servlet、filter、listener、interceptor之间的区别和联系

    一.概念 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层. 2.filter: ...

  6. 【转载并整理】filter、servlet、interceptor、listener区别

    参考文章:https://blog.csdn.net/u013087513/article/details/56835894 一.servlet servlet是一种运行服务器端的java应用程序,具 ...

  7. servlet,listener,filter,interceptor的关系

    1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层.最早支持 Servlet 技术 ...

  8. 【转】servlet/filter/listener/interceptor区别与联系

    原文:https://www.cnblogs.com/doit8791/p/4209442.html 一.概念: 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台 ...

  9. [转]web.xml中servlet ,filter ,listener ,interceptor的作用与区别

    原文链接:https://blog.csdn.net/netdevgirl/article/details/51483273 一.概念: 1.servlet:servlet是一种运行服务器端的java ...

随机推荐

  1. 为什么说在js当中所有类的父类是Object类

    代码如下所示: function Parent(add,net,no,teacher) { this.add = add; this.net = net; this.no = no; this.tea ...

  2. Linux下Redis集群环境的搭建

    一.安装redis(使用redis3.0版本) 1.需要gcc环境,如果没有执行命令安装gcc yum install gcc-c++ 2.下载redis3.0的源码包并上传至服务器 3.解压源码包 ...

  3. cache buffers chains以及热块解决方案

    cache buffers chains以及热块解决方案 今天是2013-10-10,今天下午我调休了,中午饭过后从14点一直睡到16点,这种感觉真爽.  之前学习过关于buffer cache的ca ...

  4. Android 长截屏原理

    https://android-notes.github.io/2016/12/03/android%E9%95%BF%E6%88%AA%E5%B1%8F%E5%8E%9F%E7%90%86/   a ...

  5. 图论之最短路径(1)——Floyd Warshall & Dijkstra算法

    开始图论学习的第二部分:最短路径. 由于知识储备还不充足,暂时不使用邻接表的方法来计算. 最短路径主要分为两部分:多源最短路径和单源最短路径问题 多源最短路径: 介绍最简单的Floyd Warshal ...

  6. WEB安全第二篇--用文件搞定服务器:任意文件上传、文件包含与任意目录文件遍历

    零.前言 最近做专心web安全有一段时间了,但是目测后面的活会有些复杂,涉及到更多的中间件.底层安全.漏洞研究与安全建设等越来越复杂的东东,所以在这里想写一个系列关于web安全基础以及一些讨巧的pay ...

  7. 【BZOJ2957】楼房重建 分块

    [BZOJ2957]楼房重建 Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子 ...

  8. 【Android】Android背景选择器selector用法汇总

    一.创建xml文件,位置:drawable/xxx.xml,同目录下记得要放相关图片 <?xml version="1.0" encoding="utf-8&quo ...

  9. 输入一个网站地址到网站展现的过程以及APR协议(鬼知道中间经历了什么)

    以前只知道输入一个网站,然后看着返回琳琅满目的内容,其实中间经历的过程和步骤太多了.为了满足好奇心以及学习需要,特查阅了资料将其记录下来以备后续自己复习. 从我在地址栏输入www.zhihu.com ...

  10. 170523、快速提升你 MySQL 数据库的段位

    MySQL 数据库知识脉络,大致可以分为四大模块: ● MySQL 体系结构: ● MySQL 备份恢复: ● MySQL 高可用集群: ● MySQL 优化. 从四大模块中,抽离7个部分给大家做分析 ...