2024.10月11日--- SpringMVC拦截器

拦截器

1 回顾过滤器:

Servlet规范中的三大接口:==Servlet接口,Filter接口、Listener接口。==

过滤器接口,是Servlet2.3版本以来,定义的一种小型的,可插拔的Web组件,可以用来拦截和处理Servlet容器的请求和响应过程。以便查看,提取或以某种方式操作正在客户端与服务器端之间交换的数据。

过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截。Filter 接口中定义了三个方法。

  • init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。「注意」:这个方法必须执行成功,否则过滤器会不起作用。

  • doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。

  • destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。

2 拦截器的简介

SpringMVC里的拦截器是面向切面编程AOP的一个具体实现,用于对请求做预处理。

1)什么是拦截器:

在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略

2)为什么需要拦截器:

在做身份认证或者是进行日志的记录时,我们需要通过拦截器达到我们的目的。最常用的登录拦截、或是权限校验、或是防重复提交、或是根据业务像12306去校验购票时间,总之可以去做很多的事情

3 拦截器的应用

步骤1):自定义一个类,实现HandlerInterceptor接口,或者继承HandlerInterceptorAdapter抽象类

步骤2):根据自己的需求,重写方法

方法1:boolean preHandle()- 想要在执行Controller之前执行拦截,就重写该方法。- 存在多个interceptor时,它们基于链式方式调用,按照注册的先后顺序依次执行。- 方法返回true时,后续有拦截器,就继续执行拦截器,没有就执行controller.- 方法返回false时,后续任何内容都不执行了,直接返回浏览器
​
​
方法2:void postHandle():会在Controller执行后,视图渲染之前调用该方法。因此可以在这个阶段,对将要返回给客户端的ModelAndView进行处理。
​
方法3:void afterCompletion:- 该方法会在视图渲染后被调用,主要是用来进行资源清理工作。- 多个拦截器时,依旧是先执行先注册的拦截器的afterCompletion方法- 不管处理器是否抛出异常,该方法都将执行。

步骤3)在spring的配置文件中配置拦截器(或者配置类中也可以)

4 拦截器执行流程

4.1 拦截器的执行时机

4.2 拦截器和过滤器一起应用时的执行时机

5 拦截器的应用场景

日志记录:记录请求信息的日志,以便进行信息监控、信息统计等;

权限检查:如登录校验,在处理器处理之前先判断是否已经登录;

性能监控:通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。

通用行为:读取 Cookie 得到用户信息并将用户对象放入请求,从而方便后续流程使用。还有如提取 Locale、Theme 信息等,只要是多个处理器都需要的都可以用拦截器来实现。

6 当前路径绑定权限拦截器

package com.ssm.netctoss.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * 步骤1):自定义一个类,实现HandlerInterceptor接口,或者继承HandlerInterceptorAdapter抽象类
 * 步骤2):根据自己的需求,重写方法
 * 步骤3)在spring的配置文件中配置拦截器(或者配置类中也可以)
 */
public class CurrentPathPrivilegeInterceptor implements HandlerInterceptor {
    /**
     *
     * @param request   请求对象
     * @param response  响应对象
     * @param handler   请求路径对应的Controller里的方法对象(反射机制)
     *                   /fee/findByPage
     *                  public String findByPage(){
     *                      ........
     *                  }
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("----------preHandle------------");
        System.out.println("-------注意:需要给每个用户添加0,8,9权限,在数据库中-----------");
        System.out.println("-------注意:需要给每个用户添加0,8,9权限,在数据库中-----------");
        System.out.println("-------注意:需要给每个用户添加0,8,9权限,在数据库中-----------");
        //获取请求路径:
        String uri = request.getRequestURI();
        int currentPrivilege = -1;
        if(uri.contains("/toIndex")){
            currentPrivilege = 0;
        }else if(uri.contains("/role/")){
            currentPrivilege = 1;
        }else if(uri.contains("/admin/")){
            currentPrivilege = 2;
        }else if(uri.contains("/fee/")) {
            currentPrivilege = 3;
        }else if(uri.contains("/account/")) {
            currentPrivilege = 4;
        }else if(uri.contains("/service/")) {
            currentPrivilege = 5;
        }else if(uri.contains("/bill/")) {
            currentPrivilege = 6;
        }else if(uri.contains("/report/")) {
            currentPrivilege = 7;
        }else if(uri.contains("/user/show")) {
            currentPrivilege = 8;
        }else if(uri.contains("/user/toUpdate")) {
            currentPrivilege = 9;
        }
        request.getSession().setAttribute("currentPrivilege", currentPrivilege);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("----------postHandle------------");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("----------afterCompletion------------");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

 编写导航高亮提示

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<div id="navi">
   <ul id="menu">
      <li><a href="../index/toIndex" class="<c:choose><c:when test="${currentPrivilege==0}">index_on</c:when><c:otherwise>index_off</c:otherwise></c:choose>"></a></li>
      <li><a href="../role/findByPage" class="<c:choose><c:when test="${currentPrivilege==1}">role_on</c:when><c:otherwise>role_off</c:otherwise></c:choose>"></a></li>
      <li><a href="../admin/findByPage" class="<c:choose><c:when test="${currentPrivilege==2}">admin_on</c:when><c:otherwise>admin_off</c:otherwise></c:choose>"></a></li>
      <li><a href="../fee/findByPage" class="<c:choose><c:when test="${currentPrivilege==3}">fee_on</c:when><c:otherwise>fee_off</c:otherwise></c:choose>"></a></li>
      <li><a href="../account/findByPage" class="<c:choose><c:when test="${currentPrivilege==4}">account_on</c:when><c:otherwise>account_off</c:otherwise></c:choose>"></a></li>
      <li><a href="../service/searchService" class="<c:choose><c:when test="${currentPrivilege==5}">service_on</c:when><c:otherwise>service_off</c:otherwise></c:choose>"></a></li>
      <li><a href="../bill/bill_list.html" class="bill_off"></a></li>
      <li><a href="../report/report_list.html" class="report_off"></a></li>
      <li><a href="../user/showUserInfo" class="<c:choose><c:when test="${currentPrivilege==8}">information_on</c:when><c:otherwise>information_off</c:otherwise></c:choose>"></a></li>
      <li><a href="../user/toUpdatePwd" class="<c:choose><c:when test="${currentPrivilege==9}">password_on</c:when><c:otherwise>password_off</c:otherwise></c:choose>"></a></li>
   </ul>
</div>

 7 登录拦截

package com.ssm.netctoss.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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

/**
 * 使用拦截器,来完成用户是否登录过。  如果没有登录,应该跳转到登录页面,强制其登录
 *
 * 返回值:
 *  false:  不执行后续的代码,包括Controller
 *  true:  执行后续的代码,如果有下一个拦截器,就执行下一个拦截器的preHandle。如果没有拦截器,执行Controller
 */
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("----------LoginInterceptor的preHandle-----------");
        //获取session,从中获取绑定的信息
        Object loginAdmin = request.getSession().getAttribute("LOGINADMIN");
        if (loginAdmin == null) {
            //没有登录过,就跳转
            response.sendRedirect(request.getContextPath()+"/login/toLogin");
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("----------LoginInterceptor的postHandle----------");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("----------LoginInterceptor的afterCompletion----------");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

 8 权限验证拦截器

package com.ssm.netctoss.interceptor;

import com.ssm.netctoss.pojo.Admin;
import com.ssm.netctoss.pojo.Privilege;
import com.ssm.netctoss.pojo.Role;
import com.ssm.netctoss.service.AdminService;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 登录用户的权限校验拦截:
 *      比如:登录用户,只能访问管理员,资费,账务,没有其他权限,那么相应的导航栏,有的能访问,有的不能访问
 *
 *
 *      admin_info ----> admin_role---->role_info--->role_privilege-->privilege_info
 *      caocao                           管理员1 100                   1 2 3
 *                                       营业员  200                   3 4 5 6
 *                                       经理    300                   7
 */
public class PrivilegeInterceptor extends HandlerInterceptorAdapter {
   /**
     * 因为拦截器是运行在Spring容器中维护的。(Bean),因此可以使用DI注入其他业务层/控制层的各种类型属性
     */
   //    @Resource
   //    private AdminService adminService;
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      //获取当前登录用户的所有权限
      Admin admin = (Admin) request.getSession().getAttribute("LOGINADMIN");
      //创建一个Set集合,用于存储该用户的所有权限(privilegeId,name)
      Set<Privilege> privileges = new HashSet<Privilege>();  // Privileges实体类要重新hashCode和equals方法
      List<Role> roles = admin.getRoles();
      for (Role role : roles) {
         //添加进集合,并去重
         privileges.addAll(role.getPrivileges());
      }
      /*从当前的请求路径上获取对应的绑定权限*/
      int currentPrivilege = (Integer)(request.getSession().getAttribute("currentPrivilege"));
      /*查看当前路径的绑定权限是否在当前用户的权限集合里,如果没有,就跳转进行提示*/
      for (Privilege privilege : privileges) {
         if(privilege.getPrivilegeId()==currentPrivilege){
            return true;
         }
      }
      //如果在循序期间,没有遇到return true,说明要访问的路径用户是没有该权限的。因此要做一个跳转
      response.sendRedirect(request.getContextPath()+"/login/nopower");
      return false;
   }
}

注册拦截器

 <!--注册拦截器:    拦截器的执行顺序与配置的先后有关系。  先配置的先执行-->
    <mvc:interceptors>
        <!--配置登录拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login/login"/>
            <mvc:exclude-mapping path="/login/getCheckCode"/>
            <mvc:exclude-mapping path="/login/toLogin"/>
            <bean class="com.ssm.netctoss.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
        <!--  当前路径的权限绑定拦截器      -->
        <mvc:interceptor>
            <!-- 需要拦截的各种路径:-->
            <mvc:mapping path="/**"/>
<!--            <mvc:mapping path="/login/toIndex"/>-->
<!--            <mvc:mapping path="/login/showUserInfo"/>-->
            <!-- 不需要拦截的路径:-->
            <mvc:exclude-mapping path="/login/toLogin"/>
            <mvc:exclude-mapping path="/login/login"/>
            <mvc:exclude-mapping path="/login/logout"/>
            <!-- 手动配置拦截器的Bean对象           -->
            <bean class="com.ssm.netctoss.interceptor.CurrentPathPrivilegeInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login/*"/>
            <bean class="com.ssm.netctoss.interceptor.PrivilegeInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

 9 拦截器与过滤器的比较

**①** 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  

**②** 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  

**③** 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  

**④** 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  

**⑤** 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

**⑥** 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

**⑦ **过滤器和拦截器触发时机、时间、地方不一样

**⑧**过滤器包裹住servlet,servlet包裹住拦截器。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1000题-计算机网络系统概述

术语定义与其他术语的关系SDU&#xff08;服务数据单元&#xff09;相邻层间交换的数据单元&#xff0c;是服务原语的表现形式。在OSI模型中&#xff0c;SDU是某一层待传送和处理的数据单元&#xff0c;即该层接口数据的总和。 - SDU是某一层的数据集&#xff0c;准备传递给下一…

ICDE 2024最新论文分享|BEEP:容量约束下能够对抗异常干扰的航运动态定价系统

论文简介 本推文详细介绍了上海交通大学高晓沨教授和陈贵海教授团队发表在顶级学术会议ICDE 2024上发表的最新论文《Corruption Robust Dynamic Pricing in Liner Shipping under Capacity Constraint》&#xff0c;该论文的学生作者为胡永祎、李雪嫣、魏熙锴&#xff0c;合作…

Midjourney零基础学习

Midjourney学习笔记TOP04 Midjourney的各种参数设置 Midjourney的用户操作界面没有醒目的工具栏、属性栏&#xff0c;所有的操作都是通过调用各种指令和参数进行的。 【MJ Version】 Midjourney在2023年3月份就已经更新到了V5版本&#xff0c;V5版本除了画质有所提升外&#…

MacOS 同时配置github、gitee和gitlab密钥

MacOS 同时配置github、gitee和gitlab密钥 1 在终端中新建 ~/.ssh目录 1.1 生成GitHub、Gitee和Gitlab的SSH密钥对 ssh-keygen -t ed25519 -C "xxxxxxxxxxx.com" -f ~/.ssh/id_ed25519_gitee ssh-keygen -t ed25519 -C "xxxxxxxxxxx.com" -f ~/.ssh/id_…

TikTok代理IP全面使用指南

对于那些希望通过社交媒体打造个人品牌的人来说&#xff0c;TikTok是现在热门的平台&#xff0c;他的流量与曝光不可小觑&#xff0c;相信很多跨境营销会选择他进行多账号营销。问题是&#xff0c;TikTok多账号很容易遇到封禁问题&#xff0c;那么如何解决&#xff1f; 一、什么…

无人机集群路径规划:5种优化算法(SFOA、APO、GOOSE、CO、PIO)求解无人机集群路径规划,提供MATLAB代码

一、单个无人机路径规划模型介绍 无人机三维路径规划是指在三维空间中为无人机规划一条合理的飞行路径&#xff0c;使其能够安全、高效地完成任务。路径规划是无人机自主飞行的关键技术之一&#xff0c;它可以通过算法和模型来确定无人机的航迹&#xff0c;以避开障碍物、优化…

pytest:4种方法实现 - 重复执行用例 - 展示迭代次数

简介&#xff1a;在软件测试中&#xff0c;我们经常需要重复执行测试用例&#xff0c;以确保代码的稳定性和可靠性。在本文中&#xff0c;我们将介绍四种方法来实现重复执行测试用例&#xff0c;并显示当前迭代次数和剩余执行次数。这些方法将帮助你更好地追踪测试执行过程&…

Python | Leetcode Python题解之第468题验证IP地址

题目&#xff1a; 题解&#xff1a; class Solution:def validIPAddress(self, queryIP: str) -> str:if queryIP.find(".") ! -1:# IPv4last -1for i in range(4):cur (len(queryIP) if i 3 else queryIP.find(".", last 1))if cur -1:return &q…

Jupyter的使用分享

文章目录 碎碎念安装方法1.安装Anaconda方法2.通过库的安装方式 启动使用教程1.指定目录打开2.启动后的简单使用 小结 碎碎念 前情提示 之前与许多小伙伴交流的时候&#xff0c;发现大家对于pycharm更容易上手&#xff08;可能是比较好设置中文的原因&#xff09;&#xff0c;在…

【MySQL】-- 表的操作

文章目录 1. 查看所有表1.1 语法 2. 创建表2.1 语法2.2 示例2.3 表在磁盘上对应的文件 3. 查看表结构3.1 语法3.2 示例 4. 查看创建表的语句5. 修改表5.1 语法5.2 示例5.2.1 向表中添加一列5.2.2 修改某列的长度5.2.3 重命名某列5.2.4 删除某个字段5.2.5 修改表名 6. 删除表6.1…

CANoe_调用C#控件的方法_DEMO方法演示

1、DEMO存放位置 D:\Users\Public\Documents\Vector\CANoe\Sample Configurations 11.0.96\CAN\MoreExamples\ActiveX_DotNET_Panels 每个人的电脑因为有区别存放位置不一样 2、控件制作--使用C#控件可以直接制作 3、控件代码 using System; using System.Collections; usi…

Java调用WebService接口实践案例

最终效果 在网上找了一个免费的webservice接口简单做个测试,可以正常返回结果 public static void main(String[] args) {String url = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";String xmlData = "<soapenv:Envelope xmlns:soapen…

springboot 整合spring ai实现 基于知识库的客服问答

rag 需求产生的背景介绍&#xff1a; 在使用大模型时&#xff0c;常遇到的问题之一是模型可能产生幻觉&#xff0c;即生成的内容缺乏准确性。此外&#xff0c;由于大模型不直接访问企业的专有数据&#xff0c;其响应可能会显得泛泛而谈&#xff0c;不够精准或具体&#xff0c;…

onnx代码解读

一、定义 torch.jit.trace 相关代码解读onnx 内部实现 3 查看是否为aten 算子aten 算子实现torch.autograd.Functions 算子实现自定义算子实现查找未实现的节点一次性发现所有的未实现 aten 算子 二、实现 torch.jit.trace 相关代码解读 1. torch.jit.script() : 将其转换为…

CSD(computational storage devices)架构介绍

CSD&#xff08;computational storage devices&#xff09;架构介绍 前言一、CSD与传统SSD的架构对比二、为什么要采用FPGA三、FPGA缺点四、个人总结reference 前言 虽然一直有接触CSD&#xff0c;但一直对其原理和架构知之甚少&#xff0c;半知不解。今天&#xff0c;趁着我还…

CSS计数器

CSS 中的计数器类似于变量&#xff0c;可以实现简单的计数功能&#xff0c;并将结果显示在页面上&#xff0c;在早期的网站上应用比较广泛。要实现计数器需要用到以下几个属性&#xff1a; counter-reset&#xff1a;创建或者重置计数器&#xff1b;counter-increment&#xf…

机器学习框架(含实例说明)

机器学习框架是用于开发和部署机器学习模型的软件库和工具集。它们提供了一系列的算法、工具和基础设施&#xff0c;帮助开发者更高效地构建、训练和部署机器学习模型。以下是一些主要的机器学习框架及其详细介绍&#xff1a; 1. TensorFlow TensorFlow 是由Google开发的开源…

盘点2024年双十一最值得入手的好物,双十一必买清单大汇总

随着科技的飞速发展&#xff0c;数码产品已成为我们生活中不可或缺的伙伴。2024年双十一购物狂欢节即将来临&#xff0c;众多消费者早已摩拳擦掌&#xff0c;准备在这个年度盛事中淘到心仪的数码好物。在这个信息爆炸的时代&#xff0c;如何从琳琅满目的商品中挑选出性价比高、…

C# WPF 仿 Android Toast 效果

转载请注明出处: https://blog.csdn.net/hx7013/article/details/142860084 主职Android, 最近需要写一些WPF的程序作为上位机&#xff0c;目前WPF的MessageBox过于臃肿&#xff0c;且想找一个内置的非阻塞的简单提示一直找不到&#xff0c;想到了Android的Toast所以写了这个扩…

如何实现C#和Python之间实时视频数据交互

我们在做RTSP|RTMP播放的时候&#xff0c;遇到好多开发者&#xff0c;他们的视觉算法大多运行在python下&#xff0c;需要高效率的实现C#和Python的视频数据交互&#xff0c;常用的方法如下&#xff1a; 方法一&#xff1a;通过HTTP请求传输视频数据 服务器端&#xff08;Pyth…