2023.12.3 关于 Spring Boot 拦截器 和 过滤器

news2024/11/19 17:37:33

目录

引言

Spring 拦截器实现

实例理解

Spring 过滤器实现

实例理解

拦截器和过滤器的区别 

出身不同

触发时机不同

底层实现不同

支持的项目类型不同

使用场景不同


引言

  • 原生 Spring AOP 实现统一拦截有两个难点
  • 难点一:定义拦截规则表达式 
  • 难点二:在切面中获取到 HttpSession

Spring 拦截器实现

  • 为了解决原生 Spring AOP 实现统一拦截的难点
  • Spring 提供了具体的实现拦截器 HandlerInterceptor
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器:执行 preHandle 方法。");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器:执行 postHandle 方法。");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器:执行 afterCompletion 方法。");
    }
}
  • preHandle 在请求方法执行前被调用,也就是在调用目标方法之前被调用
  • postHandle 在请求方法执行后被调用,但是会在 DispatcherServlet 进行渲染视图之前被执行
  • afterCompletion 会在整个请求结束之后再执行,也就是在 DispatcherServlet 渲染了对应的视图之后再执行

实例理解

  • 此处我们想要实现 用户登录验证 的判断
步骤一
  • 创建自定义拦截器,此处创建了一个 LoginInterceptor 类实现 HandlerInterceptor 接口
  • 用户登录验证 属于执行目标方法之前就应对其进行判断,所以此处重写 preHandler 方法,并在方法中编写相应的业务代码
package com.example.demo.component;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/*
* 自定义拦截器
* */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    /*
    * 调用目标方法之前执行的方法
    * 此方法返回 boolean 类型的值 如果返回的为 true 表示拦截器 验证成功 继续走后续的流程
    * 如果返回 false 则表示拦截器 验证未通过 后续的流程和目标方法不要执行了
    * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        用户登录判断业务
        HttpSession session  = request.getSession(false);
        if(session != null && session.getAttribute("session_userinfo") != null) {
//            用户已经登录
            return true;
        }
//        到达此处说明用户未登录
//        我们可以直接重定向到登录页面
//        response.sendRedirect("/login.html");
//        此处我们未写登录页面,所以我们直接返回一个 401 表示客户端错误
        response.setStatus(401);
        return false;
    }
}

步骤二
  • 将自定义拦截器加入到系统配置
  • 设置拦截规则
package com.example.demo.config;

import com.example.demo.component.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")//拦截所有的 url  /* 代表一级 /** 代表多级
                .excludePathPatterns("/user/login") //排除 url /user/login 不拦截
                .excludePathPatterns("/user/register") 
                .excludePathPatterns("/css/**") //排除 css 文件夹下的所有文件
                .excludePathPatterns("/js/**") //排除 js 文件夹下的所有文件
                .excludePathPatterns("/image/**") //排除 image 文件夹下的所有文件
        ;
    }
}

  • 设置完拦截器后的交互流程图

Spring 过滤器实现

  • 过滤器的实现可以使用 Servlet 3.0 提供的 @WebFilter 注解
  • 配置过滤的 URL 规则、实现 Filter 接口 、重写接口中的 doFilter 方法
package com.example.demo.component;

import org.springframework.stereotype.Component;

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

@Component
@WebFilter(urlPatterns = "/*")
public class TestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器:执行 init 方法");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器:开始执行 doFilter 方法");
//        请求放行
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("过滤器:结束执行 doFilter 方法");
    }

    @Override
    public void destroy() {
        System.out.println("过滤器:执行 destroy 方法");
    }
}

  • init  在容器启动时会被调用,整个程序运行期只会被调用一次,用于实现 Filter 对象的初始化
  • doFilter 具体过滤功能的实现,通过此方法对请求进行过滤处理
  • destory 用于 Filter 销毁前完成相关资源的回收工作

注意:

  • filterChain.doFilter(servletRequest,servletResponse); (请求放行)
  • 该行代码的作用是将请求传递给过滤器链中的下一个过滤器或目标资源(执行下一个流程)
  • 如果没有这行代码,那么请求将会在当前的过滤器中停止,不会继续向下传递

实例理解

  • 此处我们想实现 敏感词过滤
package com.example.demo.component;

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

@WebFilter(urlPatterns = "/*")
public class SensitiveWordsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器:执行 init 方法");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器:开始执行 doFilter 方法");
        // 获取用户提交的信息
        String message = servletRequest.getParameter("message");
        // 敏感词库
        String[] sensitiveWords = {"敏感词1", "敏感词2"};
        for (String sensitiveWord : sensitiveWords) {
            if (message.contains(sensitiveWord)) {
                message = message.replace(sensitiveWord, "*");
            }
        }
        servletRequest.setAttribute("message", message);
        // 请求放行
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("过滤器:结束执行 doFilter 方法");
    }

    @Override
    public void destroy() {
        System.out.println("过滤器:执行 destroy 方法");
    }
}

拦截器和过滤器的区别 

  • 主要有 5 个方面

出身不同

  • 拦截器 来自于 Spring 框架
  • 过滤器 来自于 Servlet 

触发时机不同

  • 请求执行顺序为:
  • 请求进入容器 ——> 进入过滤器 ——> 进入 Servlet ——> 进入拦截器 ——> 进入控制器(Controller)

底层实现不同

拦截器

  • 基于 Java 的 Servlet 规范实现的,通过实现 HandleInterceptor 接口来实现拦截器功能
  • 在 Spring Boot 框架的执行流程中,拦截器被注册在 DispatcherServlet 的 doDispatch 方法中,该方法是 Spring Boot 框架的核心方法,用于处理请求和响应
  • 程序每次执行时都会调用 doDispatch 方法,并验证拦截器链(一个应用中可以同时存在多个拦截器,每个拦截器均按提前配置好的顺序执行),之后再根据拦截器返回的结果,进行下一步的处理
  • 如果返回的是 true 则将继续调用目标方法
  • 如果返回的是 false 则直接返回验证失败给前端

过滤器

  • 基于方法回调

支持的项目类型不同

  • 拦截器 是 Spring 中的一个组件,因此拦截器即可以用在 Web 项目中,同时还可以用在 Application 或 Swing 程序中
  • 过滤器 是 Servlet 规范中定义的,所以过滤器要依赖于 Servlet 容器,它只能用在 Web 项目中

使用场景不同

  • 拦截器 更接近业务系统,所以拦截器主要用来实现项目中的业务判断,如登录判断、权限判断、日志记录等
  • 过滤器 通常是用来实现通用功能过滤的,如敏感词过滤、字符集编码设置、响应数据压缩 等

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

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

相关文章

用提问的方式来学习:冯·诺伊曼体系结构与操作系统OS

学习冯诺伊曼体系结构之前,我们要本着两个问题来学习: 什么是冯诺伊曼体系结构?为什么要有冯诺伊曼体系结构? 一、冯诺伊曼体系结构 1. 什么是冯诺伊曼体系结构? 那我们就先来回答一下什么是冯诺伊曼体系结构&#x…

VMALL 商城系统

SpringBoot MySQL Vue等技术实现 技术栈 核心框架:SpringBoot 持久层框架:MyBatis 模板框架:Vue 数据库:MySQL 阿里云短信,对象存储OSS 项目包含源码和数据库文件。 效果图如下:

奥特曼被指爱权力胜过金钱;人类才是「幻觉问题」根本原因丨 RTE 开发者日报 Vol.103

开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE (Real Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有…

【网络编程】-- 05 UDP进阶之在线聊天

网络编程 6 UDP 6.2.2 UDP聊天实现 “循环实现消息的发送和接收” 接收端只能接收到消息而无法反馈交流 接收: package com.duo.chat;import java.net.DatagramPacket; import java.net.DatagramSocket;public class UdpReceiveDemo1 {public static void mai…

12月11日作业

完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示登录成功,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密码不匹配,弹…

【flink番外篇】1、flink的23种常用算子介绍及详细示例(完整版)

Flink 系列文章 一、Flink 专栏 Flink 专栏系统介绍某一知识点,并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分,比如术语、架构、编程模型、编程指南、基本的…

宝塔PostgreSQL设置数据库远程访问

宝塔PostgreSQL设置数据库远程访问 宝塔的PostgreSQL1. 添加数据库2. 打开PostgreSQL设置界面3. 修改配置4. 重载配置/重启数据库 Docker的PostgreSQL1. postgresql.conf2. pg_hba.conf3. 重启数据库 注意其他问题 宝塔PostgreSQL设置数据库远程访问?docker容器Post…

这样的Python自动化测试面试题,测开来了都不一定都会把!

十、接口自动化 10.1 接口自动化怎么测试 ( Python requestspytest 版本) 原来我们接口自动化是用 python request pytest 执行 接口自动化其实主要就是接口测试的基础上填加了断言,参数化,动态关联 做接口自动化之前,我们也会划分模块&#…

Java毕业设计 SSM SpringBoot 在线学习系统

Java毕业设计 SSM SpringBoot 在线学习系统 SSM SpringBoot 在线学习系统 功能介绍 首页 图片轮播 视频推荐 在线学习 学习介绍 评论 收藏 资料中心 资料详情 下载资料 话题讨论 文档发布 试题中心 系统公告 登录 注册学生 个人中心 试题记录 错题本 我的收藏 算法演示 结果分…

智能优化算法应用:基于蝴蝶算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于蝴蝶算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于蝴蝶算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝴蝶算法4.实验参数设定5.算法结果6.参考文献7.MA…

课后作业7.3.1:构造一个自己的小操作系统

构造一个自己的 mini 操作系统 任务描述 请实现如下功能: 1.写一个命令解释器程序 mysh.c ,其功能是接收用户输入的命令并给出反馈。要求该程序既支持内部命令 cd、sync、exit ;也支持外部命令,即可以接收 cat、ls 等命令&#x…

【电路笔记】-电位器

电位器 文章目录 电位器1、概述2、电位器类型2.1 旋转电位器2.2 滑块电位器2.3 预设和微调电位器2.4 变阻器 3、电位器示例14、电位器作为分压器5、电位器示例26、变阻器6、滑块变阻器7、线性或对数电位器8、总结 当连接的轴物理旋转时,电位计和变阻器的电阻值会发生…

【linux】yum安装时: Couldn‘t resolve host name for XXXXX

yum 安装 sysstat 报错了: Kylin Linux Advanced Server 10 - Os 0.0 B/s | 0 B 00:00 Errors during downloading metadata for repository ks10-adv-os:- Curl error (6): Couldnt resolve host nam…

Aesthetically Relevant Image Captioning 美学上相关的图像字幕

1.摘要 图像美学质量评估(AQA)旨在为图像指定数字美学等级,而图像美学字幕(IAC)旨在生成图像美学方面的文本描述。在本文中,我们研究了图像AQA和IAC,并提出了一种新的IAC方法,称为审美相关图像字幕(ARIC)。基于大多数图像的文本评…

基于ssm高校教师科研信息展示网站论文

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对高校教师科研项目展示信息管理混乱,出错率高&#xff0c…

记录 | ubuntu源码编译安装/更新boost版本

一、卸载当前的版本 1、查看当前安装的boost版本 dpkg -S /usr/include/boost/version.hpp通过上面的命令,你就可以发现boost的版本了,查看结果可能如下: libboost1.54-dev: /usr/include/boost/version.hpp 2、删除当前安装的boost sudo …

【数据结构(十·树结构的实际应用)】赫夫曼编码(3)

文章目录 1. 基本介绍1.1. 赫夫曼编码基本概念1.2. 通信领域中的编码方式1.2.1. 定长编码1.2.2. 变长编码1.2.3. 赫夫曼编码(属于变长编码的一种) 2. 实例应用-赫夫曼编码实现数据压缩2.1. 创建赫夫曼树2.2. 生成赫夫曼编码2.2.1. 生成赫夫曼树对应的赫夫曼编码表2.2.2. 赫夫曼…

初识人工智能,一文读懂强化学习的知识文集(5)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

BMP转PNG工具BMP2PNG

自己写的一个BMP转PNG工具BMP2PNG 写这个工具是因为要使用传奇的部分素材在COCOS2DX使用, 但是COCOS2DX不支持BMP 如果直接将BMP转换到PNG的话,网上找到的工具都不支持透明色转换。难道要用PS一个一个抠图吗?要累死 所以写了这个工具。一些古…

HBase 详细图文介绍

目录 一、HBase 定义 二、HBase 数据模型 2.1 HBase 逻辑结构 2.2 HBase 物理存储结构 ​2.3 数据模型 2.3.1 Name Space 2.3.2 Table 2.3.3 Row 2.3.4 Column 2.3.5 Time Stamp 2.3.6 Cell 三、HBase 基本架构 架构角色 3.1 Master 3.2 Region Server 3.3 Zo…