Java的Servlet、Filter、Interceptor、Listener

写在前面:

使用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 注解自动注册,无需其他代码。

通过@ServletComponentScan注解的方法:

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

一、Servlet

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

1、通过@ServletComponentScan自动扫描

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

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处理了请求,此时拦截器不处理)

拦截器不处理。

时间: 2024-10-01 06:25:06

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

JAVA WEB SERVLET 基础知识点

Servlet Servlet Servlet API 概述 Servlet 编写基础的Servlet应用程序 1编写和编译Servlet类 2应用程序的目录结构 3调用Servlet ServletRequest ServletResponse ServletConfig ServletContext GenericServlet 1 HTTPServlet 2 HttpServletRequest 3 HttpServletResponse 处理HTML表单 使用部署描述符 掌握Servle

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

由于最近两个月工作比较清闲,个人也比较“上进”,利用工作空余时间,也继续学习了一下,某天突然想起struts2和struts1的区别的时候,发现为什么struts1要用servlet,而struts2要用filter呢?一时又发现,servlet和filter有什么区别呢?于是看了看web.xml,一时又发现,咦,servlet.filter.listener?还有个interceptor?对于这几个概念,本应是初学者就掌握的东东了,可惜本人基础学的不好,只能是现在补课.于是就有了这篇博客. 慢

servlet/filter/listener/interceptor区别与联系(转)

由于最近两个月工作比较清闲,个人也比较"上进",利用工作空余时间,也继续学习了一下,某天突然想起struts2和struts1的区别的时候,发现为什么struts1要用servlet,而struts2要用filter呢?一时又发现,servlet和filter有什么区别呢?于是看了看web.xml,一时又发现,咦,servlet.filter.listener?还有个interceptor?对于这几个概念,本应是初学者就掌握的东东了,可惜本人基础学的不好,只能是现在补课.于是就有了这篇

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

原文:https://www.cnblogs.com/doit8791/p/4209442.html 一.概念: 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层.最早支持 Servlet 技术的是 JavaSoft 的 Java Web Server.此后,一些其它的基于 Java 的 Web Server 开始支持标准的 Servlet API.Servlet 的主要功能在

servlet/filter/listener/interceptor过滤器、监听器、拦截器区分

因为之前一直分不清过滤器和拦截器的区别,所以有了两者差不多的错觉,因此在这里总结下servlet/filter/listener/interceptor过滤器.监听器.拦截器. 在此之前先简单回顾下servlet: 概述:servlet是一种运行服务器端的java应用程序,它工作在客户端请求与服务器响应的中间层. 主要作用:在于交互式地浏览和修改数据,生成动态 Web 内容. 访问流程: 1,客户端发送请求至服务器端: 2,服务器将请求信息发送至 Servlet: 3,Servlet 生成响应内

servlet & filter & listener & interceptor

1.servlet url传来之后,就对其进行处理,之后返回或转向到某一自己指定的页面.它主要用来在业务处理之前进行控制. 2.filter url传来之后,检查之后,可保持原来的流程继续向下执行. filter可用来进行字符编码的过滤,检测用户是否登陆,禁止页面缓存等 3.servlet 与 filter 都是针对url之类的,而listener是针对对象的操作的.如: session的创建,Spring整合Struts,为Struts的action注入属性,web应用定时任务的实现,在线人数

Java Web组件Servlet、Filter、Listener

一.Servlet 类javax.servlet.http.HttpServlet; 1.是单例模式,一个web容器中只有一个实例.服务器调用它的service方法进行请求处理, service方法又根据请求的类型分别调用doGet,doPost等方法. 2.由于是单例模式,所以线程不安全 3.自定义Servlet需继承HttpServlet,并重写相应的doGet等方法.方法体内不能调用父类的该方法. web.xml注册: <servlet> <servlet-name>myse

Servlet、Filter和Listener

Java Servlet是与平台无关的服务器端组件,运行于Servlet容器中(如Tomcat),Servlet容器负责Servlet和客户端的通信以及调用Servlet的方法,Servlet和客户端的通信采用“请求/响应”的模式.Servlet可完成以下功能: 1.创建并返回基于客户请求的动态HTML页面. 2.创建可以嵌入到现有HTML页面中的HTML片段. 3.与其它服务器资源(如数据库或基于Java的应用程序)进行通信. 4.接收多个客户端的输入,并将结果广播到多个客户端上,例如,Ser

Servlet相关 Filter相关 Listener相关

Java Servlet是与平台无关的服务器端组件,运行于Servlet容器中(如Tomcat),Servlet容器负责Servlet和客户端的通信以及调用Servlet的方法,Servlet和客户端的通信采用"请求/响应"的模式.Servlet可完成以下功能: 1.创建并返回基于客户请求的动态HTML页面. 2.创建可以嵌入到现有HTML页面中的HTML片段. 3.与其它服务器资源(如数据库或基于Java的应用程序)进行通信. 4.接收多个客户端的输入,并将结果广播到多个客户端上,例