JavaWeb学习笔记之——Filter & Listener

Filter & Listener

1、Filter:过滤器

1.1、概念

生活中的过滤器:净水器,空气净化器,“土匪”…

在这里插入图片描述

web 中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。

过滤器的作用:

  • 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…

1.2、快速入门

  1. 步骤:
    1. 定义一个类,实现接口 Filter;
    2. 复写方法;
    3. 配置拦截路径:
      • web.xml
      • 注解

创建一个 FilterDemo1 类:

package com.example.day19_filter_listener.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * 过滤器快速入门
 */
@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo1被执行了...");

    }
}

访问 index.jsp:

在这里插入图片描述

可以发现:index.jsp 的内容无法显示,但是执行了 doFilter() 的方法。

在 doFilter() 的方法中添加 “放行” 方法:

//放行
filterChain.doFilter(servletRequest, servletResponse);

在这里插入图片描述

发现,可以展示 index.jsp 的内容了。

1.3、过滤器细节

1.3.1、web.xml 配置

修改 FilterDemo1:(注释掉注解和 “放行”)

package com.example.day19_filter_listener.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * 过滤器快速入门
 */
//@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo1被执行了...");

        //放行
        //filterChain.doFilter(servletRequest, servletResponse);
    }
}

配置 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>demo1</filter-name>
        <filter-class>com.example.day19_filter_listener.filter.FilterDemo1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>demo1</filter-name>
        <!-- 拦截路径 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

再次访问 index.jsp:

在这里插入图片描述

1.3.2、过滤器执行流程

创建 FilterDemo2:

package com.example.day19_filter_listener.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo2 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //对request对象的请求消息增强
        System.out.println("filterDemo2执行了...");

        //放行
        chain.doFilter(request, response);
        //对response对象的响应消息的增强
        System.out.println("filterDemo2回来了...");
    }
}

修改 index.jsp:

<body>
index.jsp...
    <%
        System.out.println("index.jsp...");
    %>
</body>

执行结果:

filterDemo2执行了...
index.jsp...
filterDemo2回来了...

可以看到,过滤器的执行流程如下:

  1. 执行过滤器;
  2. 执行 “放行” 后的资源;
  3. 回来执行过滤器放行代码下边的代码。
1.3.3、过滤器生命周期
  1. init:在服务器启动后,会创建 Filter 对象,然后调用 init 方法。只执行一次。用于加载资源;
  2. doFilter:每一次请求被拦截资源时,会执行。执行多次;
  3. destroy:在服务器关闭后,Filter 对象被销毁。如果服务器是正常关闭,则会执行 destroy 方法。只执行一次。用于释放资源。

创建 FilterDemo2:

package com.example.day19_filter_listener.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo3 implements Filter {
    /**
     * 在服务器启动后,会创建Filter对象,然后调用init方法,只执行一次
     * 用于加载资源
     * @param config
     * @throws ServletException
     */
    public void init(FilterConfig config) throws ServletException {
        System.out.println("init...");
    }

    /**
     * 在服务器关闭后,Filter对象被销毁,如果服务器是正常关闭,则会执行destroy方法,只执行一次
     * 用于释放资源
     */
    public void destroy() {
        System.out.println("destory...");
    }

    /**
     * 每一次请求被拦截资源时,会执行,执行多次
     * @param request
     * @param response
     * @param chain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("doFilter...");

        //放行
        chain.doFilter(request, response);
    }
}
1.3.4、过滤器配置详解
  • 拦截路径配置:

    1. 具体资源路径:/index.jsp 只有访问 index.jsp 资源时,过滤器才会被执行;
    2. 拦截目录:/user/* 访问 /user下的所有资源时,过滤器都会被执行;
    3. 后缀名拦截:*.jsp 访问所有后缀名为 jsp 资源时,过滤器都会被执行;
    4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行。
  • 拦截方式配置:资源被访问的方式

    • 注解配置:

      设置:设置 dispatcherTypes 属性

      1. REQUEST:默认值。浏览器直接请求资源;
      2. FORWARD:转发访问资源;
      3. INCLUDE:包含访问资源;
      4. ERROR:错误跳转资源;
      5. ASYNC:异步访问资源。

      创建 FilterDemo5:(演示 dispatcherTypes = DispatcherType.REQUEST,其他参数同理)

      package com.example.day19_filter_listener.filter;
      
      import javax.servlet.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      //浏览器直接请求index.jsp资源时,过滤器会被执行
      @WebFilter(value = "/index.jsp", dispatcherTypes = DispatcherType.REQUEST)
      public class FilterDemo5 implements Filter {
          public void init(FilterConfig config) throws ServletException {
          }
      
          public void destroy() {
          }
      
          @Override
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
              System.out.println("filterDemo5...");
      
              //放行
              chain.doFilter(request, response);
          }
      }
      

      浏览器直接请求index.jsp资源时,过滤器会被执行。而浏览器转发到 index.jsp 时,不会被执行。我们再创建一个 ServletDemo2 转发到 index.jsp:

      package com.example.day19_filter_listener.servlet;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      
      @WebServlet("/user/updateServlet")
      public class ServletDemo2 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doPost(request, response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              System.out.println("updateServlet");
      
              //转到到index.jsp
              request.getRequestDispatcher("/index.jsp").forward(request, response);
          }
      }
      

      我们使用浏览器直接访问 index.jsp:(过滤器被执行)

      在这里插入图片描述

      我们访问 updateServlet(转发到 index.jsp):(过滤器不会被执行)

      在这里插入图片描述

      同时,dispatcherTypes 属性也可以设置多个值:

      //浏览器直接请求和转发请求index.jsp资源时,过滤器会被执行
      @WebFilter(value = "/index.jsp", dispatcherTypes ={DispatcherType.REQUEST, DispatcherType.FORWARD})
      
    • web.xml 配置

      设置 <dispatcher></dispatcher> 标签即可。

1.3.5、过滤器链(配置多个过滤器)

执行顺序:如果有两个过滤器:过滤器 1 和过滤器 2

  1. 过滤器 1
  2. 过滤器 2
  3. 资源执行
  4. 过滤器 2
  5. 过滤器 1

创建 FilterDemo6:

package com.example.day19_filter_listener.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo6 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("filterDemo6执行了...");

        //放行
        chain.doFilter(request, response);

        System.out.println("filterDemo6回来了...");
    }
}

创建 FilterDemo7:

package com.example.day19_filter_listener.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo7 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("filterDemo7执行了...");

        //放行
        chain.doFilter(request, response);

        System.out.println("filterDemo7回来了...");
    }
}

在这里插入图片描述

过滤器先后顺序问题:

  1. 注解配置:按照类名的字符串比较规则比较,值小的先执行

    如: AFilter 和 BFilter,AFilter 就先执行了。

  2. web.xml 配置: <filter-mapping> 谁定义在上边,谁先执行


2、Listener

2.1、概念

web 的三大组件之一。

时间监听机制:

  • 事件:一件事情
  • 事件源:事件发生的地方
  • 监听器:一个对象
  • 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码

2.2、ServletContextListener

监听 ServletContext 对象的创建和销毁。

方法:

  • void contextDestroyed(ServletContextEvent sce):ServletContext 对象被销毁之前会调用该方法
  • void contextInitialized(ServletContextEvent sce):ServletContext 对象创建后会调用该方法

步骤:

  1. 定义一个类,实现 ServletContextListener 接口
  2. 复写方法
  3. 配置

创建一个类 ContextLoaderListener 继承 ServletContextListener,复写其中的方法:

package com.example.day19_filter_listener.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextLoaderListener implements ServletContextListener {
    /**
     * 监听ServletContext对象创建。ServletContext对象服务器启动后自动创建
     * 在服务器启动后自动调用
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext对象被创建了...");
        ServletContextListener.super.contextInitialized(sce);
    }

    /**
     * 在服务器关闭后,SevletContext对象被销毁。当服务器关闭后方法被调用
     * @param sce
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext对象被销毁了...");
        ServletContextListener.super.contextDestroyed(sce);
    }
}

配置 web.xml:

<listener>
    <listener-class>com.example.day19_filter_listener.listener.ContextLoaderListener</listener-class>
</listener>

启动服务器:

在这里插入图片描述

关闭服务器:

在这里插入图片描述

跟 Servlet 的生命周期很像!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值