2023.12.3 关于 Spring 拦截器 和 过滤器

目录

引言

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 项目中

使用场景不同

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

双12取消!淘宝年终好价节对商家有何影响?电商直播到底怎么玩差异化?

据淘宝商家服务大厅显示,今年“双12”活动取消,并更改为平台大型活动“淘宝年终好价节”。淘宝“双12”一直以来都是除了“双11”和“618”之外很重要的电商促销活动,该活动于2012年首次推出,至今已经持续进行了10年。…

数实融合!低代码推动工业数字化转型走“深”向“实”

当下,“数字化、智能化”已经不再是新鲜词。毕竟,在早几年前就已经有企业喊出大举进军数字化的口号,轰轰烈烈的数字化转型运动也持续了很长一段时间,有一些业内人士甚至判断“如今的企业数字化已经走过了成熟期,来到了…

数字与数学基础问题

关卡名 数字与数学基础问题 我会了✔️ 内容 1.数字里统计的处理技巧 ✔️ 2.必须熟练掌握溢的处理方法 ✔️ 3.掌握进制的处理方法 ✔️ 1. 数字统计专题 统计一下特定场景下的符号,或者数字个数等是一类非常常见的问题 。如果按照正常方式强行统计&#xf…

蓝桥杯物联网竞赛_STM32L071_9_按键矩阵扩展模块

原理图: 矩阵按键原理图: 实验板接口原理图: 得到对应图: 扫描按键原理: 按键的COLUMN1、2、3分别制0,每次只允许其中一个为0其他都是1(POW1和POW2正常状况为上拉),当有…

S32K116新建工程Debug可以运行,冷启动无法运行问题分析

S32K116使用IAR建立工程后,软件debug可以运行,断电冷启动无法运行。 这种现象基本上都是RAM未初始化导致,由于Debug时,调试器会自动初始化芯片,很多问题都不会暴露处理。 大家可以开一下Startup的汇编文件,…

LInux组管理及拓展

目录 一、Linux组管理 (一)、组的概述 1.概述 2.作用 (二)、组操作 1.创建 2.修改 3.删除 4.添加用户 二、用户信息查看 (一)、id (二)、finger (三&#x…

Go 语言中的函数调用。

更好的观看体验,请点击——函数调用 | YinKais Blog 本文将从函数的调用惯例和参数传递方法两个方面分别介绍函数执行的过程。 1、调用惯例 对于不同的编程语言, 它们在调用函数的时候往往都使用相同的语法: somefunction(arg0, arg1) 虽…

你离高级开发只差这些IntelliJ IDEA Debug使用技巧

目录 引言 IntelliJ IDEA,由JetBrains(捷克共和国)开发的一款强大的Java集成开发环境(IDE),因其丰富的功能、智能的代码辅助以及用户友好的界面设计,在全球范围内广受Java开发者的喜爱&#xf…

VPS服务器”性价比之王”系列:RackNerd

2023 黑五!!!新 Ryzen 系列 洛杉矶dc02机房重新补货! 支付方式:支付宝、PayPal、信用卡、数字货币 2023 黑五促销活动(限量) CPU内存硬盘(SSD)流量带宽价格(续费同价)购买链接1核768 MB15GB…

“数”说新语向未来 | GBASE南大通用2023媒体交流会成功举办

在当前国家信创战略加速实施,及国民经济数字化转型,叠加驱动信息化行业加速发展的大形势下,以“数说新语-GBASE南大通用开放创新再领航”为主题的2023 GBASE南大通用媒体交流日活动在GBASE天津总部举行。来自IT168、ITPUB、韩锋频道、自主可控…

freeRTOS创建任务

一.动态创建任务 1.函数xTaskCreate() BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数const char * const pcName, // 任务的名字const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节void * const pvParameters, // …

elment-table设置el-table-column的label里面的文字换行居中显示

效果图如下&#xff1a; 直接上代码&#xff1a; <el-table class"ut-mt-2" row-key"company" default-expand-all:data"stateQuery.data" style"width: 100%":tree-props"{ children: departList, hasChildren: hasChildre…

Java 设计模式——备忘录模式

目录 1.概述2.结构3.案例实现3.1.“白箱”备忘录模式3.2.”黑箱”备忘录模式 4.优缺点5.使用场景 1.概述 &#xff08;1&#xff09;备忘录模式 (Memento Pattern) 又称为快照模式&#xff0c;是一种行为型设计模式&#xff0c;它提供了一种保存和恢复对象状态的机制。备忘录模…

Vue3使用vue-baidu-map-3x百度地图

安装vue-baidu-map-3x&#xff1a; // vue3 $ npm install vue-baidu-map-3x --save// vue2 $ npm install vue2-baidu-map --save 全局注册/局部注册&#xff1a; import { createApp } from vue import App from ./App.vue import BaiduMap from vue-baidu-map-3xconst app …

SpringBoot 注入RedisTemplat 启动报错

需求 因为需要限制部门内多个人员同一时间操作同一批客户的需求&#xff0c;考虑下决定用Redis滑动窗口实现自过期以及并发校验。 问题 新建了个Redis工具类封装RedisTemplat 操作&#xff0c;到启动时却发现无法正常启动&#xff0c;报错注入错误。 The injection point has…

leetcode做题笔记1038. 从二叉搜索树到更大和树

给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c; 二叉搜索树 满足下列约束条件&#xff1a; 节点的左子树仅包含键 小于 节点键的节点。节点的右子树仅包含键 大于 节点键的节点。左右…

Spring 概述

1 了解Spring框架 1.1 框架 框架&#xff0c;特指为解决一个开放性问题而设计的具有一定约束性的基础架构。在此架构上可以根据具体问题进行扩展和定制&#xff0c;添加更多的组成部分&#xff0c;从而更迅速和方便地构建完整的解决问题方案。 框架&#xff0c;是一种可重用…

spark无法执行pi_如何验证spark搭建完毕

在配置yarn环境下的spark时&#xff0c;执行尚硅谷的以下命令发现报错&#xff0c;找不到这个也找不到那个&#xff0c;尚硅谷的代码是 bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master yarn \ --deploy-mode cluster \ ./examples/jars/spark-exam…

初试占比7成!只考一门数据结构+学硕复录比1:1的神仙学校,大连交通大学考情分析

大连工业大学 考研难度&#xff08;☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、24专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1014字&#xff0c;预计阅读&#xff1a;3分钟 2023考情概况 大连工业…

企业电子招投标系统源码之电子招投标系统建设的重点和未来趋势

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…