Filter Listener Interceptor

news2025/1/16 3:36:13

文章目录

    • 第一章 Filter
      • 1. 目标
      • 2. 内容讲解
        • 2.1 Filter的概念
        • 2.2 Filter的作用
        • 2.3 Filter的入门案例
          • 2.3.1 案例目标
          • 2.3.2 代码实现
            • 2.3.2.1 创建ServletDemo01
            • 2.3.2.2 创建EncodingFilter
        • 2.4 Filter的生命周期
          • 2.4.1 回顾Servlet生命周期
            • 2.4.1.1 Servlet的创建时机
            • 2.4.1.2 Servlet的销毁时机
          • 2.4.2 Filter的生命周期和生命周期方法
        • 2.5 过滤器匹配规则
          • 2.5.1 过滤器匹配的目的
          • 2.5.2 四种匹配规则
            • 2.5.2.1 精确匹配
            • 2.5.2.2 模糊匹配
            • 2.5.2.3 扩展名匹配
            • 2.5.2.4 匹配Servlet名称
        • 2.6 过滤器链
          • 2.6.1 过滤链的概念
          • 2.6.2 过滤器链的顺序
          • 2.6.3 过滤器链案例
            • 2.6.3.1 创建ServletDemo01
            • 2.6.3.2 创建多个Filter拦截Servlet
    • 第二章 扩展案例: 使用Filter过滤非法字符
      • 非法字符过滤案例V1版本
        • 1. 目标
        • 2. 代码实现
      • 非法字符过滤案例V2版本
        • 1. 目标
        • 2. 代码实现
      • 非法字符过滤案例V3版本
        • 1.目标
        • 2. 代码实现
    • 第三章 Listener
      • 1. 目标
      • 2. 内容讲解
        • 2.1 观察者模式简介
        • 2.2 监听器的简介
          • 2.2.1 监听器的概念
          • 2.2.2 Servlet监听器的分类(了解)
            • 2.2.2.1 ServletContextListener
            • 2.2.2.2 HttpSessionListener
            • 2.2.2.3 ServletRequestListener
            • 2.2.2.4 ServletContextAttributeListener
            • 2.2.2.5 HttpSessionAttributeListener
            • 2.2.2.6 ServletRequestAttributeListener
            • 2.2.2.7 HttpSessionBindingListener
            • 2.2.2.8 HttpSessionActivationListener
        • 2.3 ServletContextListener的使用
          • 2.3.1 作用
          • 2.3.2 使用场景
          • 2.3.3 代码实现
            • 2.3.3.1 创建监听器类
            • 2.3.3.2 注册监听器
    • 第四章 拦截器
      • 1、概念
        • ①拦截器和过滤器解决类似的问题
          • [1]生活中坐地铁的场景
          • [2]程序中
        • ②拦截器 VS 过滤器
          • [1]相似点
          • [2]不同点
          • [3]选择
      • 2、使用
        • ①创建拦截器类
          • [1]实现接口
          • [2]继承类
        • ②注册拦截器
          • [1]默认拦截全部请求
          • [2]配置拦截路径
            • (1)精确匹配
            • (2)模糊匹配:匹配单层路径
            • (3)模糊匹配:匹配多层路径
          • [3]配置不拦截路径
        • ③多个拦截器执行顺序
      • 3、案例

第一章 Filter

1. 目标

  • 了解什么是Filter
  • 了解Filter的作用
  • 掌握Filter的使用
  • 了解Filter的生命周期
  • 掌握过滤器链的使用

2. 内容讲解

2.1 Filter的概念

Filter:一个实现了特殊接口(Filter)的Java类. 实现对请求资源(jsp,servlet,html,)的过滤的功能. 过滤器是一个运行在服务器的程序, 优先于请求资源(Servlet或者jsp,html)之前执行. 过滤器是javaweb技术中最为实用的技术之一

2.2 Filter的作用

Filter的作用是对目标资源(Servlet,jsp)进行过滤,其应用场景有: 登录权限检查,解决网站乱码,过滤敏感字符等等

2.3 Filter的入门案例
2.3.1 案例目标

实现在请求到达ServletDemo01之前解决请求参数的中文乱码

2.3.2 代码实现
2.3.2.1 创建ServletDemo01

web.xml代码

<servlet>
    <servlet-name>servletDemo01</servlet-name>
    <servlet-class>com.atguigu.ServletDemo01</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>servletDemo01</servlet-name>
    <url-pattern>/ServletDemo01</url-pattern>
</servlet-mapping>

ServletDemo01代码

package com.atguigu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Js
 * 日期2023-05-18  08:53
 */
public class ServletDemo01 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        System.out.println("ServletDemo01接收到了一个请求..."+username);
    }
}

前端页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <form action="/webday12/demo01" method="post">
        用户名<input type="text" name="username"/><br/>
        <input type="submit"/>
    </form>
</body>
</html>

如果此时没有Filter,那么客户端发送的请求直接到达ServletDemo01,中文请求参数就会发生乱码

2.3.2.2 创建EncodingFilter

web.xml代码

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.atguigu.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <!--url-pattern表示指定拦截哪些资源-->
    <url-pattern>/demo01</url-pattern>
</filter-mapping>

EncodingFilter代码

package com.atguigu.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author Js
 * 日期2023-05-18  08:56
 * 编写过滤器的步骤:
 * 1. 写一个类实现Filter接口,并且重写方法
 * 2. 在web.xml中配置该过滤器的拦截路径
 */
public class EncodingFilter implements Filter {
    @Override
    public void destroy() {
        
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //解决请求参数的乱码
        HttpServletRequest request = (HttpServletRequest) req;
        request.setCharacterEncoding("UTF-8");

        //每次有请求被当前filter接收到的时候,就会执行doFilter进行过滤处理
        System.out.println("EncodingFilter接收到了一个请求...");

        //这句代码表示放行
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        
    }

}
2.4 Filter的生命周期
2.4.1 回顾Servlet生命周期
2.4.1.1 Servlet的创建时机

Servlet默认在第一次接收请求的时候创建,我们可以通过<load-on-startup>标签配置Servlet在服务器启动的时候创建

2.4.1.2 Servlet的销毁时机

Servlet会在服务器关闭或者将项目从服务器上移除的时候销毁

2.4.2 Filter的生命周期和生命周期方法
生命周期阶段执行时机生命周期方法
创建对象Web应用启动时init方法,通常在该方法中做初始化工作
拦截请求接收到匹配的请求doFilter方法,通常在该方法中执行拦截过滤
销毁Web应用卸载前destroy方法,通常在该方法中执行资源释放
2.5 过滤器匹配规则
2.5.1 过滤器匹配的目的

过滤器匹配的目的是指定当前过滤器要拦截哪些资源

2.5.2 四种匹配规则
2.5.2.1 精确匹配

指定被拦截资源的完整路径:

<!-- 配置Filter要拦截的目标资源 -->
<filter-mapping>
    <!-- 指定这个mapping对应的Filter名称 -->
    <filter-name>FilterDemo01</filter-name>

    <!-- 通过请求地址模式来设置要拦截的资源 -->
    <url-pattern>/demo01</url-pattern>
</filter-mapping>

上述例子表示要拦截映射路径为/demo01的这个资源

2.5.2.2 模糊匹配

相比较精确匹配,使用模糊匹配可以让我们创建一个Filter就能够覆盖很多目标资源,不必专门为每一个目标资源都创建Filter,提高开发效率。

在我们配置了url-pattern为/user/*之后,请求地址只要是/user开头的那么就会被匹配。

<filter-mapping>
    <filter-name>Target02Filter</filter-name>

    <!-- 模糊匹配:前杠后星 -->
    <!--
        /user/demo01
        /user/demo02
        /user/demo03
		/demo04
    -->
    <url-pattern>/user/*</url-pattern>
</filter-mapping>

极端情况:/*匹配所有请求

2.5.2.3 扩展名匹配
<filter>
    <filter-name>Target04Filter</filter-name>
    <filter-class>com.atguigu.filter.filter.Target04Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Target04Filter</filter-name>
    <url-pattern>*.png</url-pattern>
</filter-mapping>

上述例子表示拦截所有以.png结尾的请求

2.5.2.4 匹配Servlet名称
<filter-mapping>
    <filter-name>Target05Filter</filter-name>

    <!-- 根据Servlet名称匹配 -->
    <servlet-name>Target01Servlet</servlet-name>
</filter-mapping>
2.6 过滤器链
2.6.1 过滤链的概念

一个请求可能被多个过滤器所过滤,只有当所有过滤器都放行,请求才能到达目标资源,如果有某一个过滤器没有放行,那么请求则无法到达后续过滤器以及目标资源,多个过滤器组成的链路就是过滤器链

在这里插入图片描述

2.6.2 过滤器链的顺序

过滤器链中每一个Filter执行的顺序是由web.xml中filter-mapping配置的顺序决定的。

2.6.3 过滤器链案例
2.6.3.1 创建ServletDemo01

web.xml代码

<servlet>
    <servlet-name>servletDemo01</servlet-name>
    <servlet-class>com.atguigu.ServletDemo01</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>servletDemo01</servlet-name>
    <url-pattern>/ServletDemo01</url-pattern>
</servlet-mapping>

ServletDemo01代码

public class ServletDemo01 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ServletDemo01接收到了请求...");
    }
}
2.6.3.2 创建多个Filter拦截Servlet
<filter-mapping>
    <filter-name>TargetChain03Filter</filter-name>
    <url-pattern>/Target05Servlet</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>TargetChain02Filter</filter-name>
    <url-pattern>/Target05Servlet</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>TargetChain01Filter</filter-name>
    <url-pattern>/Target05Servlet</url-pattern>
</filter-mapping>

第二章 扩展案例: 使用Filter过滤非法字符

非法字符过滤案例V1版本

1. 目标

判断评论内容中是否包含某个固定的非法字符串,如果包含则请求无法到达CommentServlet

2. 代码实现

前端页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>评论页面</title>
</head>
<body>
    <form action="/webday12/illegal/comment" method="post">
        评论内容<input type="text" name="content"/>
        <input type="submit"/>
    </form>
</body>
</html>

EncodingFilter的代码,用于解决乱码

package com.atguigu.filter;

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

/**
 * @author Js
 * 日期2023-05-18  10:19
 */
public class EncodingFilter implements Filter {
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //解决乱码
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {

    }

}

IllegalFilter的代码,用于过滤非法字符

package com.atguigu.filter;

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

/**
 * @author Js
 * 日期2023-05-18  10:22
 */
public class IllegalCharFilter implements Filter {
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1. 获取客户端提交的评论内容
        String content = req.getParameter("content");
        if (content != null) {
            //2. 判断content中是否包含非法字符
            if (content.contains("你大爷的")) {
                resp.getWriter().write("评论内容中包含非法字符,评论发布失败!!!");
                return;
            }
        }
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {

    }

}

CommentServlet的代码,用于发表评论

package com.atguigu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Js
 * 日期2023-05-18  10:17
 */
public class CommentServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 获取评论内容
        String content = request.getParameter("content");
        //2. 向客户端输出评论内容
        response.getWriter().write("恭喜你评论成功,评论内容是:"+content);
    }
}

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>EncodingFilter</filter-name>
        <filter-class>com.atguigu.filter.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>IllegalCharFilter</filter-name>
        <filter-class>com.atguigu.filter.IllegalCharFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>IllegalCharFilter</filter-name>
        <url-pattern>/illegal/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>CommentServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.CommentServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CommentServlet</servlet-name>
        <url-pattern>/illegal/comment</url-pattern>
    </servlet-mapping>
</web-app>

非法字符过滤案例V2版本

1. 目标

在第一个版本的基础之上,将固定的非法字符串替换成从illegal.txt文件中读取非法字符串

2. 代码实现

IllegalFilter的代码

package com.atguigu.filter;

import javax.servlet.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Js
 * 日期2023-05-18  10:22
 */
public class IllegalCharFilter implements Filter {
    private List<String> illegalTextList = new ArrayList<>();
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1. 获取客户端提交的评论内容
        String content = req.getParameter("content");
        if (content != null) {
            //3. 判断content中是否包含非法字符
            for (String illegalText : illegalTextList) {
                if (content.contains(illegalText)) {
                    resp.getWriter().write("评论内容中包含非法字符,评论发布失败!!!");
                    return;
                }
            }
        }
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        //在这里读取illegal.txt文件,就只需要在项目部署的时候读取一次
        //将字节输入流进行包装--->InputStreamReader()----->BufferedReader()---->readLine
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(IllegalCharFilter.class.getClassLoader().getResourceAsStream("illegal.txt"), "UTF-8"));
            String illegalText = null;
            while ((illegalText = bufferedReader.readLine()) != null) {
                //将读到的那个字符串存储到集合中
                illegalTextList.add(illegalText);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

其它的代码和V1版本相同

非法字符过滤案例V3版本

1.目标

在第二版本的基础上,实现CommentServlet发布评论内容的时候将评论内容中的非法字符替换成*

2. 代码实现

IllegalFilter的代码

package com.atguigu.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Js
 * 日期2023-05-18  10:22
 */
public class IllegalCharFilter implements Filter {
    private List<String> illegalTextList = new ArrayList<>();
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //使用动态代理改变req对象的getParameter方法
        HttpServletRequest request = (HttpServletRequest) req;
        Class<? extends HttpServletRequest> clazz = request.getClass();
        HttpServletRequest proxyRequest = (HttpServletRequest) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //改变getParameter()方法
                if(method.getName().equals("getParameter")){
                    //1. 调用原本的getParameter()方法,先获取到请求参数
                    String oldValue = (String) method.invoke(request, args);
                    //2. 判断oldValue中是否包含非法字符,如果包含则将非法字符替换成*
                    for (String illegalText : illegalTextList) {
                        if(oldValue.contains(illegalText)){
                            //非法字符串有几个字符就生成几个*
                            String star = "";
                            for (int i = 0; i < illegalText.length(); i++) {
                                star += "*";
                            }
                            //然后使用star替换oldValue中的非法字符串
                            oldValue = oldValue.replace(illegalText,star);
                        }
                    }
                    return oldValue;
                }
                return method.invoke(request,args);
            }
        });

        //放行过去的请求,一定要是代理请求
        chain.doFilter(proxyRequest, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        //在这里读取illegal.txt文件,就只需要在项目部署的时候读取一次
        //将字节输入流进行包装--->InputStreamReader()----->BufferedReader()---->readLine
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(IllegalCharFilter.class.getClassLoader().getResourceAsStream("illegal.txt"), "UTF-8"));
            String illegalText = null;
            while ((illegalText = bufferedReader.readLine()) != null) {
                //将读到的那个字符串存储到集合中
                illegalTextList.add(illegalText);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

其它代码和V2版本相同

第三章 Listener

1. 目标

  • 了解观察者模式
  • 了解监听器的概念
  • 掌握ServletContextListener的使用

2. 内容讲解

2.1 观察者模式简介

观察者模式是二十三中设计模式之一,它是指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式

在这里插入图片描述

  • 观察者:监控『被观察者』的行为,一旦发现『被观察者』触发了事件,就会调用事先准备好的方法执行操作。
  • 被观察者:『被观察者』一旦触发了被监控的事件,就会被『观察者』发现。
2.2 监听器的简介
2.2.1 监听器的概念

监听器:专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。
Servlet监听器:Servlet规范中定义的一种特殊类,它用于监听Web应用程序中的ServletContext,HttpSession 和HttpServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。

2.2.2 Servlet监听器的分类(了解)
2.2.2.1 ServletContextListener

作用:监听ServletContext对象的创建与销毁

方法名作用
contextInitialized(ServletContextEvent sce)ServletContext创建时调用
contextDestroyed(ServletContextEvent sce)ServletContext销毁时调用

ServletContextEvent对象代表从ServletContext对象身上捕获到的事件,通过这个事件对象我们可以获取到ServletContext对象。

2.2.2.2 HttpSessionListener

作用:监听HttpSession对象的创建与销毁

方法名作用
sessionCreated(HttpSessionEvent hse)HttpSession对象创建时调用
sessionDestroyed(HttpSessionEvent hse)HttpSession对象销毁时调用

HttpSessionEvent对象代表从HttpSession对象身上捕获到的事件,通过这个事件对象我们可以获取到触发事件的HttpSession对象。

2.2.2.3 ServletRequestListener

作用:监听ServletRequest对象的创建与销毁

方法名作用
requestInitialized(ServletRequestEvent sre)ServletRequest对象创建时调用
requestDestroyed(ServletRequestEvent sre)ServletRequest对象销毁时调用

ServletRequestEvent对象代表从HttpServletRequest对象身上捕获到的事件,通过这个事件对象我们可以获取到触发事件的HttpServletRequest对象。另外还有一个方法可以获取到当前Web应用的ServletContext对象。

2.2.2.4 ServletContextAttributeListener

作用:监听ServletContext中属性的创建、修改和销毁

方法名作用
attributeAdded(ServletContextAttributeEvent scab)向ServletContext中添加属性时调用
attributeRemoved(ServletContextAttributeEvent scab)从ServletContext中移除属性时调用
attributeReplaced(ServletContextAttributeEvent scab)当ServletContext中的属性被修改时调用

ServletContextAttributeEvent对象代表属性变化事件,它包含的方法如下:

方法名作用
getName()获取修改或添加的属性名
getValue()获取被修改或添加的属性值
getServletContext()获取ServletContext对象
2.2.2.5 HttpSessionAttributeListener

作用:监听HttpSession中属性的创建、修改和销毁

方法名作用
attributeAdded(HttpSessionBindingEvent se)向HttpSession中添加属性时调用
attributeRemoved(HttpSessionBindingEvent se)从HttpSession中移除属性时调用
attributeReplaced(HttpSessionBindingEvent se)当HttpSession中的属性被修改时调用

HttpSessionBindingEvent对象代表属性变化事件,它包含的方法如下:

方法名作用
getName()获取修改或添加的属性名
getValue()获取被修改或添加的属性值
getSession()获取触发事件的HttpSession对象
2.2.2.6 ServletRequestAttributeListener

作用:监听ServletRequest中属性的创建、修改和销毁

方法名作用
attributeAdded(ServletRequestAttributeEvent srae)向ServletRequest中添加属性时调用
attributeRemoved(ServletRequestAttributeEvent srae)从ServletRequest中移除属性时调用
attributeReplaced(ServletRequestAttributeEvent srae)当ServletRequest中的属性被修改时调用

ServletRequestAttributeEvent对象代表属性变化事件,它包含的方法如下:

方法名作用
getName()获取修改或添加的属性名
getValue()获取被修改或添加的属性值
getServletRequest ()获取触发事件的ServletRequest对象
2.2.2.7 HttpSessionBindingListener

作用:监听某个对象在Session域中的创建与移除

方法名作用
valueBound(HttpSessionBindingEvent event)该类的实例被放到Session域中时调用
valueUnbound(HttpSessionBindingEvent event)该类的实例从Session中移除时调用

HttpSessionBindingEvent对象代表属性变化事件,它包含的方法如下:

方法名作用
getName()获取当前事件涉及的属性名
getValue()获取当前事件涉及的属性值
getSession()获取触发事件的HttpSession对象
2.2.2.8 HttpSessionActivationListener

作用:监听某个对象在Session中的序列化与反序列化。

方法名作用
sessionWillPassivate(HttpSessionEvent se)该类实例和Session一起钝化到硬盘时调用
sessionDidActivate(HttpSessionEvent se)该类实例和Session一起活化到内存时调用

HttpSessionEvent对象代表事件对象,通过getSession()方法获取事件涉及的HttpSession对象。

2.3 ServletContextListener的使用
2.3.1 作用

ServletContextListener是监听ServletContext对象的创建和销毁的,因为ServletContext对象是在服务器启动的时候创建、在服务器关闭的时候销毁,所以ServletContextListener也可以监听服务器的启动和关闭

2.3.2 使用场景

将来学习SpringMVC的时候,会用到一个ContextLoaderListener,这个监听器就实现了ServletContextListener接口,表示对ServletContext对象本身的生命周期进行监控。

2.3.3 代码实现
2.3.3.1 创建监听器类
package com.atguigu.listener;

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

/**
 * 包名:com.atguigu.listener
 *
 * @author Js
 * 日期2023-05-18  14:10
 * ServletContextLisneter监听器可以监听服务器的启动和关闭
 * 1. contextInitialized()方法可以监听服务器的启动
 * 2. contextDestroyed()方法可以监听服务器的关闭
 */
public class MyContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("服务器启动了...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("服务器关闭了...");
    }
}

2.3.3.2 注册监听器
<!--配置Listener-->
<listener>
    <listener-class>com.atguigu.listener.MyContextListener</listener-class>
</listener>

第四章 拦截器

1、概念

①拦截器和过滤器解决类似的问题
[1]生活中坐地铁的场景

为了提高乘车效率,在乘客进入站台前统一检票:

在这里插入图片描述

[2]程序中

在程序中,使用拦截器在请求到达具体 handler 方法前,统一执行检测。

在这里插入图片描述

②拦截器 VS 过滤器
[1]相似点

三要素相同

  • 拦截:必须先把请求拦住,才能执行后续操作
  • 过滤:拦截器或过滤器存在的意义就是对请求进行统一处理
  • 放行:对请求执行了必要操作后,放请求过去,让它访问原本想要访问的资源
[2]不同点
  • 工作平台不同
    • 过滤器工作在 Servlet 容器中
    • 拦截器工作在 SpringMVC 的基础上
  • 拦截的范围
    • 过滤器:能够拦截到的最大范围是整个 Web 应用
    • 拦截器:能够拦截到的最大范围是整个 SpringMVC 负责的请求
  • IOC 容器支持
    • 过滤器:想得到 IOC 容器需要调用专门的工具方法,是间接的
    • 拦截器:它自己就在 IOC 容器中,所以可以直接从 IOC 容器中装配组件,也就是可以直接得到 IOC 容器的支持
[3]选择

功能需要如果用 SpringMVC 的拦截器能够实现,就不使用过滤器。

2、使用

①创建拦截器类
[1]实现接口
public class Process01Interceptor implements HandlerInterceptor {
 
    Logger logger = LoggerFactory.getLogger(this.getClass());
 
    // 在处理请求的目标 handler 方法前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        logger.debug("Process01Interceptor preHandle方法");
         
        // 返回true:放行
        // 返回false:不放行
        return true;
    }
 
    // 在目标 handler 方法之后,渲染视图之前
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 
        logger.debug("Process01Interceptor postHandle方法");
        
    }
 
    // 渲染视图之后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        
        logger.debug("Process01Interceptor afterCompletion方法");
        
    }
}

单个拦截器执行顺序:

  • preHandle() 方法
  • 目标 handler 方法
  • postHandle() 方法
  • 渲染视图
  • afterCompletion() 方法
[2]继承类

在较低版本的 SpringMVC 中,实现 HandlerInterceptor 接口需要把所有抽象方法都实现。但是又不是每个方法都需要使用,导致代码比较繁琐。

此时可以通过继承 HandlerInterceptorAdapter 类同样可以创建拦截器类。HandlerInterceptorAdapter 类中已经给 HandlerInterceptor 接口提供了默认实现,我们继承后不需要把每个方法都实现,只需要把有用的方法重写即可。

在 SpringMVC 较高版本(例如:5.3版本以上)中,HandlerInterceptor 接口已经借助 JDK 1.8 新特性让每个抽象方法都给出了默认实现,所以 HandlerInterceptorAdapter 这个类被标记为过时。

@Deprecated
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

}
②注册拦截器
[1]默认拦截全部请求
<!-- 注册拦截器 -->
<mvc:interceptors>
    
    <!-- 直接通过内部 bean 配置的拦截器默认拦截全部请求(SpringMVC 范围内) -->
    <bean class="com.atguigu.mvc.interceptor.Process01Interceptor"/>
</mvc:interceptors>
[2]配置拦截路径
(1)精确匹配
<!-- 具体配置拦截器可以指定拦截的请求地址 -->
<mvc:interceptor>
    <!-- 精确匹配 -->
    <mvc:mapping path="/common/request/one"/>
    <bean class="com.atguigu.mvc.interceptor.Process03Interceptor"/>
</mvc:interceptor>
(2)模糊匹配:匹配单层路径
<mvc:interceptor>
    <!-- /*匹配路径中的一层 -->
    <mvc:mapping path="/common/request/*"/>
    <bean class="com.atguigu.mvc.interceptor.Process04Interceptor"/>
</mvc:interceptor>
(3)模糊匹配:匹配多层路径
<mvc:interceptor>
    <!-- /**匹配路径中的多层 -->
    <mvc:mapping path="/common/request/**"/>
    <bean class="com.atguigu.mvc.interceptor.Process05Interceptor"/>
</mvc:interceptor>
[3]配置不拦截路径
        <mvc:interceptor>
            <!-- /**匹配路径中的多层 -->
            <mvc:mapping path="/common/request/**"/>
 
            <!-- 使用 mvc:exclude-mapping 标签配置不拦截的地址 -->
            <mvc:exclude-mapping path="/common/request/two/bbb"/>
 
            <bean class="com.atguigu.mvc.interceptor.Process05Interceptor"/>
        </mvc:interceptor>
③多个拦截器执行顺序
  • preHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置顺序调用各个 preHandle() 方法。
  • 目标 handler 方法
  • postHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 postHandle() 方法。
  • 渲染视图
  • afterCompletion() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 afterCompletion() 方法。

3、案例

一个网站有 5 个资源,其中两个无须登录即可访问,另外三个需要登录后才能访问。如果不登录就访问那三个资源,会自动跳转到登录页面并给出提示:请登录后再操作。

提示:在拦截器中,将数据存入请求域、转发或重定向请求都需要使用原生对象来完成,SpringMVC 并没有提供 Model、ModelMap 等 API 供我们使用。

访问资源的请求地址可参考:

  • 公共资源1:/public/resource/one
  • 公共资源2:/public/resouce/two
  • 私密资源1:/private/resouce/one
  • 私密资源2:/private/resouce/two
  • 私密资源3:/private/resouce/three

[

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1569594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JSON的定义和基本使用

1、JSON的特点: JSON是一种轻量级的数据交换格式&#xff0c;是由字符串化的键值对构成。基于网络的前后端通信&#xff0c;数据在服务端和客户端之间进行传输&#xff0c;采用的就是JSON的格式来进行交互。JSON采用完全独立于语言的文本格式&#xff0c;JSON的数据格式完全独…

【VSCode】修改插件地址

不想放在原始C盘下面C:\Users\{用户}\.vscode\extensions为了后续存储空间考虑&#xff0c;想通过添加环境变量创建名为VSCODE_EXTENSIONS的环境变量&#xff0c;内容指向vs Code扩展所在目录即可 直接配置环境变量&#xff0c;不要在有空格的文件夹下面 变量名称&#xff1a;…

C语言要点细细梳理——番外:运算符优先级

C语言中的运算符优先级决定了在没有括号的情况下&#xff0c;表达式中的各个部分应如何求值。这个优先级是固定的&#xff0c;并且遵循一定的规则。当运算符的优先级相同时&#xff0c;运算的方向&#xff08;从左到右或从右到左&#xff09;则称为运算符的结合性。 下面是一个…

中间件漏洞!!!

上次好像记得讲过了框架漏洞&#xff0c;&#xff08;weblogic不是&#xff09;那么&#xff0c;今天我们就来讲一些中间件的漏洞 1.Apache解析漏洞 众所周知&#xff0c;Apache是一个非常出名的中间件&#xff0c;本来呢&#xff0c;他是不存在漏洞的&#xff0c;但是如果用…

OpenAI推出VoiceEngine语音引擎技术:让声音更逼真,更富情感

继openAI GPT3.5免登录后&#xff0c;OpenAI最近推出了一款名为VoiceEngine的语音引擎技术&#xff0c;这技术能通过简单的文本输入和15秒的音频样本&#xff0c;就能生成跟原始说话者声音一模一样的语音&#xff0c;不仅逼真&#xff0c;还充满了情感。 这VoiceEngine技术&am…

三、keepalived双机热备

一、双机热备概述 1、为什么需要双机热备&#xff1a; 双机热备主要为了解决服务器的单点故障问题。 在主机 MASTER 宕机之后可以马上切换到备选服务器 BACKUP。 服务器规划&#xff1a; 2、克隆产生web01服务器&#xff1a; (1) 基于LNMP克隆生成Web01服务器&#xff1a; (…

[计算机知识] TCP/IP网络模型、MySQL的结构

TCP/IP网络模型 应用层 给用户提供应用功能&#xff0c;如HTTP, DNS 应用层处于用户态&#xff0c;传输层及以下处于内核态 传输层 给应用层提供网络支持&#xff0c;如TCP, UDP TCP提供稳定、面向连接的网络传输协议 应用层的数据可能会太大&#xff0c;就需要进行拆分…

深入浅出 -- 系统架构之分布式架构

​​​​​​分布式架构&#xff1a; 根据业务功能对系统做拆分&#xff0c;每个业务功能模块作为独立项目开发&#xff0c;称为一个服务。 当垂直应用越来越多时&#xff0c;应用之间的交互不可避免&#xff0c;可将共用的基础服务或核心模块抽取出来作为独立服务&#xff0c…

与机器对话:ChatGPT 和 AI 语言模型的奇妙故事

原文&#xff1a;Talking to Machines: The Fascinating Story of ChatGPT and AI Language Models 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 从 ELIZA 到 ChatGPT&#xff1a;会话式人工智能的简史 会话式人工智能是人工智能&#xff08;AI&#xff09;的一个分…

【C++ STL迭代器】iterator

文章目录 【 1. 迭代器的属性 】【 2. 不同容器支持的迭代器 】【 3. 迭代器的定义方式 】【 4. 实例 】4.1 定义方式&#xff1a;正向迭代器和反向迭代器4.2 迭代器属性&#xff1a;前向迭代、双向迭代、随机迭代4.2 迭代器的遍历方法4.3 auto关键字 自动指定迭代器定义类型 背…

Pycharm安装及使用图文教程(附下载地址)

1. Pycharm简介 大家在使用Python的时候往往会选择一款自己熟悉的编译器。大多数Python使用者会选择PyCharm这款软件来进行Python的学习与开发。 关于PyCharm&#xff0c;PyCharm是一种Python IDE&#xff0c;带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具&a…

每日五道java面试题之ZooKeeper篇(一)

目录&#xff1a; 第一题. ZooKeeper 是什么&#xff1f;第二题. Zookeeper 文件系统第三题. Zookeeper 怎么保证主从节点的状态同步&#xff1f;第四题. 四种类型的数据节点 Znode第五题 . Zookeeper Watcher 机制 – 数据变更通知 第一题. ZooKeeper 是什么&#xff1f; Zoo…

Python爬虫:http和https介绍及请求

HTTP和HTTPS 学习目标&#xff1a; 记忆 http、https的概念和区别记忆 浏览器发送http请求的过程记忆 http请求头的形式记忆 http响应头的形式了解 http响应状态码 1 为什么要复习http和https 在发送请求&#xff0c;获取响应的过程中 就是发送http或https的请求&#xff0c…

grep无法使用完整的正则表达式

问题描述 grep无法使用完整的正则表达式&#xff0c;比如前置断言、后置断言、\d和\t、\n等 问题原因 使用了扩展正则&#xff0c;而不是perl正则。规则和perl正则不同 从文档上讲得很清楚&#xff1a; -E PATTERN is an extended regular expression 他是扩展表达式&#…

网络安全 | 什么是负载均衡器?

关注WX&#xff1a; CodingTechWork 介绍 负载均衡是在多个服务器之间有效分配网络流量的过程。负载均衡的目的是优化应用程序的可用性&#xff0c;并确保良好的终端用户体验。负载均衡可协助高流量网站和云计算应用程序应对数百万个用户请求&#xff0c;从而保证客户请求不会…

Driver not loaded之记录Qt访问MySql的解决经历

对于这个问题的本质原因&#xff0c;我也搞不明白&#xff0c;所以记录的方法不一定对所有人行之有效。我的目的很简单&#xff0c;就是把数据库用起来&#xff0c;经过查找网上资料&#xff0c;最终把数据库跑起来了。因此记录如下&#xff1a; 1&#xff0c;出现这个问题是缺…

【Linux】网络基础常识{OSI七层模型/ TCP/IP / 端口号 /各种协议}

文章目录 1.网络常识1.0DHCP协议1. 1IP地址/MAC地址/ARP协议是什么&#xff1f;IP/MACARP&#xff1a;IP ⇒ MAC 1.2手机连接wifi的原理 SSID与BSSID手机连接wifiSSID与BSSID 1.3手机如何通过“数据/流量”上网&#xff1f;1.4电脑连接wifi的原理&#xff1f;电脑通过热点上网…

Linux云计算之Linux基础3——Linux基本认识操作

1、终端 终端(terminal)&#xff1a;人和系统交互的必要设备&#xff0c;人机交互最后一个界面&#xff08;包含独立的输入输出设备&#xff09; 物理终端(console)&#xff1a;直接接入本机器的键盘设备和显示器虚拟终端(tty)&#xff1a;通过软件方式虚拟实现的终端。它可以…

各种滤波算法

各种滤波算法 1. 半径离群点去除(Radius Outlier Removal&#xff0c;半径滤波)2. 统计离群点剔除(Statistical Outlier Removal, 统计滤波)3. 体素网格将采样(voxel grid downsampling)4. 最远点采样(Farthest Point Sampling, FPS)5. 正态空间将采样(Normal Space Sampling, …

第六期丨酷雷曼无人机技能培训

第6期无人机技能提升培训 盼望着盼望着&#xff0c;第六期无人机技能提升培训会终于如期和大家见面了。 2024年1月1日&#xff0c;国务院、中央军事委员会颁布《无人驾驶航空器飞行管理暂行条例》&#xff0c;对民用无人机飞行活动实施更为严格的规范约束&#xff0c;越来越多…