拦截器 之 用户登录判断

news2024/10/7 6:44:53

spring boot 拦截器的实现需要有两步:

拦截器

自定义一个拦截器

package com.example.demo.common;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

@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;
        }
        // 用户没登陆就设置一个 401 状态码,不然就是一个空白页面
        response.setStatus(401);
        return false;
    }
}

将拦截器设置到配置项中,并设定拦截规则

package com.example.demo.config;

import com.example.demo.common.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 LoginConfig implements WebMvcConfigurer { // 使用这个接口中的方法把自定义拦截器添加到项目配置中

    @Autowired
    private LoginInterceptor loginInterceptor;

    // 添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)  // registry 是一个注册器,往里面添加自定义的拦截器
                .addPathPatterns("/**")  // 所有的 url 都会进行拦截判断
                .excludePathPatterns("/user/login")  // 设置不进行拦截的 url
                .excludePathPatterns("/user/reg");

    }
}

运行结果:

拦截器实现原理

实现源码

        所有的 Controller 执⾏都会通过⼀个调度器 DispatcherServlet 来实现,而所有⽅法都会执行 DispatcherServlet 中的 doDispatch 调度方法。从源码可以看出在开始执行 Controller 之前,会先调用 预处理方法 applyPreHandle, 在 applyPreHandle 中会获取所有的拦截器 HandlerInterceptor 并执⾏拦截器中的 preHandle ⽅法,这样就会前⾯定义的拦截器对应上了,此时⽤户登录权限的验证⽅法就会执⾏,这就是拦截器的实现原理。

统一异常处理

        在写代码的时候经常会遇到各种错误,但每个地方都写一个异常处理就不太合适,或者直接不管就让程序报错也不合适,相对较好的办法就是:先保证程序不会直接报错,然后再返回一些信息给前端。因此就需要专门创建个处理异常的类。

        统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执⾏某个通知,也就是执⾏某个⽅法事件,具体实现代码如下:
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;

@ControllerAdvice  // 这个注解表示当前类会监控所有的异常,并且根据项目启动而启动
@ResponseBody
public class ResponseAdvice  {  // 继承这个接口表示对数据进行加工(而不是返回一个数据)

    @ExceptionHandler(NullPointerException.class)  // 定义异常的类型,空指针异常
    public Object NullPointerException(NullPointerException e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", -1);
        result.put("msg ", "空指针:" + e.getMessage());
        result.put("data", null);
        return result;
    }

    @ExceptionHandler(Exception.class)  // 默认的异常处理,当具体的异常匹配不到就会执行
    public Object Exception(Exception e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", -1);
        result.put("msg ", "Exception:" + e.getMessage());
        result.put("data", null);
        return result;
    }

}

运行结果:

统一数据返回格式

        主要作用:降低前端和后端的沟通成本、有利于项⽬统⼀数据的维护和修改。
        统⼀的数据返回格式可以使用 @ControllerAdvice + ResponseBodyAdvice 的⽅式实现,具体实现代码如下:
package com.example.demo.common;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;

@ControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice {  // 继承这个接口表示对数据进行加工(而不是返回一个数据)

    // 是否执行 beforeBodyWrite 方法,true = 执行,重写返回结果
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    // 执行数据的重写的方法,这个是保底的做法,保证不会抛异常,但是重写的返回结果都是千篇一律的
    // 假设如果数据是 HashMap 格式的,那么就认为数据统一了是正确的,否则就重写成 HashMap 的格式
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        // 如果原始数据 body 是 HashMap 格式的话
        if (body instanceof HashMap) {
            return body;
        }

        // 不是的话就把原始数据重写成 HashMap 格式
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg ", "修改了数据");
        result.put("data", body);  // body 是原始的返回值
        return result;
    }
}

运行结果:

但是当返回值为 String 并且需要重写数据的时候:

        这是因为:1. 当返回的是 String 类型的时候,2. 在统一数据返回之前会先将 String 转换成 HashMap,3. 然后再将 HashMap 转换成 application / json 字符串传给前端。

        出错的原因发生在第 3 步:转换的时候会对原 body 的类型进行判断:1. String 类型,会使用 StringHttpMessageConverter 进行类型转换、2. 非 String 类型,会使用 HttpMessageConverter 进行类型转换。

        因此解决方案就有两种解决方案:

1. 将 StringHttpMessageConverter 从配置文件中去掉

@Configuration
public class MyConfig implements WebMvcConfigurer {
     // 移除 StringHttpMessageConverter
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.removeIf(converter -> converter instanceof StringHttpMessageConverter);
    }
}

2. 在统一数据重写时,单独处理,返回一个 String 字符串而不是 HashMap

// 不是的话就把原始数据重写成 HashMap 格式
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg ", "修改了数据");
        result.put("data", body);  // body 是原始的返回值
        if (body instanceof String) {
            // 把对象转成 json 再进行返回
            return objectMapper.writeValueAsString(result);
        }
        return result;

运行结果:

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

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

相关文章

【React】极客园--01.项目前置准备

项目搭建 基于CRA创建项目 CRA是一个底层基于webpack快速创建React项目的脚手架工具 # 使用npx创建项目 npx create-react-app react-jike# 进入到项 cd react-jike# 启动项目 npm start调整项目目录结构 -src-apis 项目接口函数-assets 项目资源文件&…

Flume基础教程

Apache Flume教程 资料来源&#xff1a;Apache Flume - Introduction (tutorialspoint.com) Flume是一个标准的、简单的、健壮的、灵活的、可扩展的工具&#xff0c;用于将从各种数据生产者(web服务器)中所产生的数据抽取到Hadoop中。在本教程中&#xff0c;我们将使用简单的…

内部类介绍

内部类&#xff08;Inner Class&#xff09;是在另一个类的内部定义的类。它可以访问外部类的所有成员&#xff0c;包括私有成员。内部类有两种主要形式&#xff1a;局部内部类&#xff08;定义在方法内部&#xff09;和成员内部类&#xff08;定义在类的内部&#xff0c;但不在…

《Nest系列 - 2. Nest 代码生成器,让你告别base代码书写!!!》

紧接上文我们做一些核心梳理 核心梳理&#xff1a; /controllers目录&#xff1a;存放控制器文件&#xff0c;每个控制器对应一组路由和请求处理方法。控制器处理来自客户端的HTTP请求&#xff0c;并返回相应的响应。/modules目录&#xff1a;存放模块文件&#xff0c;每个模块…

第十一章:接口

接口 文章目录 接口一、简介1.1 接口是什么1.2 接口的作用1.3 接口的开发与调用1.4 接口的组成 二、RESTful API三、json-server四、接口测试工具五、接口的创建 一、简介 1.1 接口是什么 接口是前后端通信的桥梁 简单理解&#xff1a;一个接口就是 服务中的一个路由规则&am…

7.华为交换机端口配置链路聚合Eth-trunk

目的&#xff1a;两台华为交换机端口配置链路聚合 LSW1配置 [Huawei]interface Eth-Trunk 1 [Huawei-Eth-Trunk1]q [Huawei]int g0/0/1 [Huawei-GigabitEthernet0/0/1]eth-trunk 1 [Huawei-GigabitEthernet0/0/1]int g0/0/2 [Huawei-GigabitEthernet0/0/2]eth-trunk 1LSW2配置…

产品经理用好AI,最关键的一个点

前言 AI大模型已经越来越强大了&#xff0c;我们要怎么才能把它变成生产力工具&#xff1f;根据最近的一个调研发现&#xff0c;即使是在产品经理这个群体里&#xff0c;能真正用好AI去激发生产力的人也只占6%&#xff0c;也就是说其实有94%的人都还不能很好的把生成式AI转化为…

个人博客测试用例设计

个人博客测试用例设计 个人博客测试用例 分别从功能、性能、安全、兼容及界面分别展开 个人博客测试用例

VST3音频插件技术介绍

一.概述 1.VST3介绍 VST3&#xff08;Virtual Studio Technology 3&#xff09;是一种音频插件格式&#xff0c;由Steinberg公司开发&#xff0c;用于在数字音频工作站&#xff08;DAW&#xff09;中使用。VST3插件可以是模拟合成器、鼓机、混响器、压缩器等多种类型的音频处理…

文件系统崩溃一致性、方法、原理与局限

前言 先提几个问题&#xff1a;什么是文件系统崩溃一致性&#xff1f;为什么会出现文件系统崩溃一致性问题&#xff1f;有哪些方法可以解这个问题&#xff1f;它们各自又有哪些局限性&#xff1f; window系统电脑异常后会蓝屏、手机死机卡顿后我们会手动给它重启&#xff0c;大…

VirtualStudio配置QT开发环境

环境 VirtualStudio2022Qt5.12.10 安装msvc工具链&#xff08;这一步不是必须的&#xff09; 打开virtual studio&#xff0c;打开Virtual Studio Installer界面选择要安装的msvc版本&#xff0c;点击安装 安装VirtualStudio扩展 在线安装 打开virtual Studio&#xff0c;…

Blurry - hackthebox

简介 靶机名称&#xff1a;Blurry 难度&#xff1a;中等 靶场地址&#xff1a;https://app.hackthebox.com/machines/605 本地环境 靶机IP &#xff1a;10.10.11.19 linux渗透机IP(kali 2024.2)&#xff1a;10.10.16.17 windows渗透机IP&#xff08;windows11&#xff0…

excel宏处理魔法代码,实现按月份统计销售额和按产品统计销售额

目录 前言第一步&#xff1a;打开文件第二步&#xff1a;选中左侧任意一个sheet双击第三步&#xff1a;粘贴 魔法代码第四步&#xff1a;点击菜单栏 运行>运行子程序和用户窗口第五步&#xff1a;切换回文件&#xff0c;我们就可以看到已经生成了月份销售额统计和产品销售额…

合合信息文档解析工具重磅升级!智能识别,效率翻倍!

官.网地址&#xff1a;合合TextIn - 合合信息旗下OCR云服务产品 智能文档处理(IDP)是利用人工智能技术,自动从复杂的非结构化和半结构化文档中抽取关键数据,并将其转换成结构化数据的技术。能够自动识别、提取并结构化处理文档中的关键信息。这种技术通常基于自然语言处理&…

经验分享,两个在线图片处理网站在线抠图和删除不需要的元素

分享两个好用的在线图片处理网站 1.在线抠图&#xff0c;图片背景消除 网址&#xff1a;https://www.remove.bg/zh 2.删除图片中不需要的对象、人物和文本。 网址&#xff1a;https://magicstudio.com/zh/magiceraser/

DLS平台:惠誉全球经济展望——今年调增至2.6%,明年调减!

摘要 尽管全球货币政策逐渐转向宽松&#xff0c;惠誉国际评级&#xff08;Fitch Ratings&#xff09;在最新的《全球经济展望》中对2024年全球经济增长进行了上调。然而&#xff0c;由于美国经济增速放缓和其他因素的影响&#xff0c;2025年的全球经济增长预期则被下调。这篇文…

最新Prompt预设词分享,DALL-E3文生图+文档分析

使用指南 直接复制使用 可以前往已经添加好Prompt预设的AI系统测试使用&#xff08;可自定义添加使用&#xff09; 支持GPTs SparkAi SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。支持GPT-4o…

从零开始:精通基于大型语言模型(LLM)的Agent应用开发

一、引言 随着人工智能技术的飞速发展&#xff0c;大型语言模型&#xff08;Large Language Model&#xff0c;简称LLM&#xff09;已经成为自然语言处理&#xff08;NLP&#xff09;领域的核心技术之一。这些模型&#xff0c;如GPT、BERT等&#xff0c;通过大量的文本数据训练…

pop链详细分析、构造(以[NISACTF 2022]babyserialize为例)

目录 [NISACTF 2022]babyserialize &#xff08;一&#xff09;理清pop链&#xff08;链尾 链头&#xff09;&#xff0c;标注步骤 1. 先找eval、flag这些危险函数和关键字样&#xff08;这是链尾&#xff09; 2.往eval()上面看 3.往$bb()上面看 4.往strtolower()上面看 …

自制调色小工具给图片加滤镜,修改图片红、绿、蓝通道及亮度,修改图片颜色

上篇&#xff1a; 上篇我们给地图添加了锐化、模糊等滤镜&#xff0c;这篇来写一个小工具给图片调色。 调色比锐化等滤镜要简单许多&#xff0c;直接拿到像素值修改即可。不需要用到卷积核。。。(*^▽^*) 核心原理就是图像结构&#xff0c;使用context.getImageData获取图像像…