当前位置: 首页 > news >正文

Spring实现[拦截器+统一异常处理+统一数据返回]

Spring拦截器

1.实现一个普通拦截器

  • 关键步骤
    • 实现 HandlerInterceptor 接口
    • 重写 preHeadler 方法,在方法中编写自己的业务代码
@Component
public class LoginInterceptor implements HandlerInterceptor {/*** 此方法返回一个 boolean,如果为 true 表示验证成功,可以继续执行后续流程* 如果是 false 表示验证失败,后面的流程不能执行* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//用户登录业务判断HttpSession session = request.getSession(false);//有session就提取,没有也不创建if(session != null && session.getAttribute(Constant.SESSION_USERINFO_KEY) != null) {//说明用户已经登录return true;}// 401 : 用户没有登录所以没有权限  403 : 用户登录了但没有权限response.setStatus(401);return false;}
}

2.将拦截器添加搭配系统配置中,并设置拦截的规则

@Configuration
public class AppConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;
//只要不是需求的页面,都进行拦截List<String> excludes = new ArrayList<String>() {{//放行数组add("/**/*.html");add("/js/**");add("/editor.md/**");add("/css/**");add("/img/**"); // 放行 img 下的所有文件add("/user/login"); // 放行登录add("/user/reg"); // 放行注册add("/art/detail"); // 放行详情页add("/user/author"); // 放行详情页个人信息的 usernameadd("/art/list"); // 放行文章分页列表的接口add("/art/totalpage"); // 放行获取文章分页的总页数add("/art/artcount"); // 放行分页列表页个人信息的 文章数量 / 也是详情页的文章数量}};@Overridepublic void addInterceptors(InterceptorRegistry registry) {//添加拦截规则InterceptorRegistration registration =registry.addInterceptor(loginInterceptor);registration.addPathPatterns("/**");//拦截器下放行 excludes 数组内的规则registration.excludePathPatterns(excludes);}
}

拦截器实现原理

用户调用–> controller ----> service ----> mapper---->数据库

实现拦截器之后:

用户调用–>拦截器预处理(拦截规则,黑白名单)----> controller ----> service ----> mapper---->数据库

实现原理源码分析

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try {processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// 步骤1,获取执行链,重要重要重要重要重要重要重要重要重要mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// 步骤2,获取适配器,重要重要重要重要重要重要重要重要重要HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}//步骤3,拦截器pre方法,重要重要重要重要重要重要重要重要重要if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}//步骤4,真正处理逻辑,重要重要重要重要重要重要重要重要重要//执行 Controller 中的业务mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);//步骤5,拦截器post方法,重要重要重要重要重要重要重要重要重要mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {dispatchException = new NestedServletException("Handler dispatch failed", err);}//步骤6,处理视图,重要重要重要重要重要重要重要重要重要processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {//步骤7,拦截器收尾方法,重要重要重要重要重要重要重要重要重要triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {if (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VVnpcXAY-1678274299650)(C:\Users\17512\AppData\Roaming\Typora\typora-user-images\1678269545822.png)]

统一异常处理

统一异常处理使用的是 @ControllerAdvice(控制器通知类) 和 @ExceptionHandler(异常处理器) 来实现。

1.创建统一封装类

2.使用 @ExceptionHandler 注解来订阅异常信息

/*** 异常类的统一处理*/
@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {@ExceptionHandler(Exception.class) // 异常类型public Object exceptionAdvice(Exception e) {return AjaxResult.fail(-1, e.getMessage());}
}

统一数据的返回

统一数据格式的返回可以使用 @ControllerAdvice + ResponseBodyAdvice 方法实现。

1.创建一个类,并添加 @ControllerAdvice

2.实现ResponseBodyAdvice接口,并且重写supports和beforeBodyWrite(统一返回对象就是在此方法中实现)

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {//内容是否需要重写//返回 true 表示重写@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}//方法返回之前调用此方法@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {// 1.本身已经是封装好的对象 判断一个对象是否为一个类if(body instanceof  HashMap) {return body;}// 2.返回类型是 String (特殊)if(body instanceof String) {ObjectMapper objectMapper = new ObjectMapper();return objectMapper.writeValueAsString(AjaxResult.success(body));}return AjaxResult.success(body);}
}

相关文章:

Spring实现[拦截器+统一异常处理+统一数据返回]

Spring拦截器 1.实现一个普通拦截器 关键步骤 实现 HandlerInterceptor 接口重写 preHeadler 方法&#xff0c;在方法中编写自己的业务代码 Component public class LoginInterceptor implements HandlerInterceptor {/*** 此方法返回一个 boolean&#xff0c;如果为 true …...

MySQL——插入加锁/唯一索引插入死锁/批量插入效率

本篇主要介绍MySQL跟加锁相关的一些概念、MySQL执行插入Insert时的加锁过程、唯一索引下批量插入可能导致的死锁情况&#xff0c;以及分别从业务角度和MySQL配置角度介绍提升批量插入的效率的方法&#xff1b;MySQL跟加锁相关的一些概念在介绍MySQL执行插入的加锁过程之前&…...

【专项训练】数组、链表

数组array: list = []链表linked list # Definition for singly-linked list. class ListNode:def __init__(self, x):self.val = xself.next =...

基于Jeecgboot前后端分离的ERP系统开发代码生成(六)

商品信息原先生成的不符合要求&#xff0c;重新生成&#xff0c;包括一个附表商品价格信息表 一、采用TAB主题一对多的模式 因为主键&#xff0c;在online表单配置是灰的&#xff0c;所以不能进行外键管理&#xff0c;只能通过下面数据库进行关联录入&#xff0c;否则online界面…...

什么?同步代码块失效了?-- 自定义类加载器引起的问题

一、背景 最近编码过程中遇到了一个非常奇怪的问题&#xff0c;基于单例对象的同步代码块似乎失效了&#xff0c;百思不得其姐。 下面给出模拟过程和最终的结论。 二、场景描述和模拟 2.1 现象描述 Database实现单例&#xff0c;在 init 方法中使用同步代码块来保证 data不…...

CHAPTER 4 文件共享 - Samba

文件共享 - Samba1 Samba1.1 Samba的软件架构1.2 搭建Samba服务器1.3 samba用户管理1. 添加用户2. 修改用户密码3. 删除用户和密码4. 查看samba用户列表5. 查看samba服务器状态1.4 samba共享设置&#xff08;配置文件详解&#xff09;1.5 访问共享目录1. windows访问2. linux客…...

深入分析@Configuration源码

文章目录一、源码时序图1. 注册ConfigurationClassPostProcessor流程源码时序图2. 注册ConfigurationAnnotationConfig流程源码时序图3. 实例化流程源码时序图二、源码解析1. 注册ConfigurationClassPostProcessor流程源码解析&#xff08;1&#xff09;运行案例程序启动类Conf…...

Unity 代码优化 内存管理优化

项目遇到了卡顿的情况 仔细检查了代码没检查出有误的地方 仔细的总结了一下可以优化的东西 解决了卡顿 记录一下 1 协程 项目之前写的关于倒计时之类的东西 都是开了个协程 虽然协程是消耗很小的线程 , 可是还是有额外消耗 而且 有很多用携程来检测销毁预制体的操作 也都放到U…...

设计模式~门面(外观)模式(Facade)-08

目录 &#xff08;1&#xff09;优点 &#xff08;2&#xff09;缺点 &#xff08;3&#xff09;使用场景 &#xff08;4&#xff09;注意事项&#xff1a; &#xff08;5&#xff09;应用实例&#xff1a; &#xff08;6&#xff09;源码中的经典应用 代码 外观模式&am…...

C++面向对象编程之一:封装

C面向对象编程三大特性为&#xff1a;封装&#xff0c;继承&#xff0c;多态。C认为万事万物皆为对象&#xff0c;对象有属性和行为。比如&#xff1a;游戏里的地图场景可以看作是长方形对象&#xff0c;属性场景id&#xff0c;有长&#xff0c;有宽&#xff0c;可能有NPC&…...

IDEA插件系列(3):Maven Helper插件

一、引言在写Java代码的时候&#xff0c;我们可能会出现Jar包的冲突的问题&#xff0c;这时候就需要我们去解决依赖冲突了&#xff0c;而解决依赖冲突就需要先找到是那些依赖发生了冲突&#xff0c;当项目比较小的时候&#xff0c;还比较依靠IEDA的【Diagrams】查看依赖关系&am…...

SAP 更改物料基本计量单位

前言部分 在SAP中物料创建后&#xff0c;一旦发生业务&#xff0c;其基本计量单位便很难修改。由于单位无法满足业务要求&#xff0c;往往会要求新建一个物料替代旧物料。这时候除了要将旧物料上所有的未清业务删除外&#xff0c;还需要替换工艺与BOM中的旧物料。特别是当出现旧…...

蓝桥web基础知识学习

HTMLCSS 知识点重要指数HTML 基础标签&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;HTML5 新特性&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;HTML5 本地存储&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;CSS 基础语法…...

Python+ChatGPT制作一个AI实用百宝箱

目录一、注册OpenAI二、搭建网站及其框架三、AI聊天机器人四、AI绘画机器人ChatGPT 最近在互联网掀起了一阵热潮&#xff0c;其高度智能化的功能能够给我们现实生活带来诸多的便利&#xff0c;可以帮助你写文章、写报告、写周报、做表格、做策划甚至还会写代码。只要与文字相关…...

Python中格式化字符串输出的4种方式

Python格式化字符串的4中方式 一、%号 二、str.format(args) 三、f-Strings 四、标准库模板 五、总结四种方式的应用场景’ 一、%号占位符 这是一种引入最早的一种&#xff0c;也是比较容易理解的一种方式.使用方式为&#xff1a; 1、格式化字符串中变化的部分使用占位符 2、…...

C#基础教程15 枚举与类

文章目录 C# 枚举(Enum)声明 enum 变量C# 类(Class)类的定义成员函数和封装C# 中的构造函数关键字 staticC# 枚举(Enum) 枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。 C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。 声明 enum 变…...

三步 让你的 vscode 自动编译ts文件

三步让你的 vscode 自动编译ts文件 TypeScript环境安装与如何在vscode实现自动编译ts文件? 文章目录三步让你的 vscode 自动编译ts文件前提条件环境安装自动编译运行监视任务时报错&#xff1f;前提条件 安装 node 环境 环境安装 tsc 作用&#xff1a;负责将ts 代码 转为 浏…...

STM32程序下载和启动方式

目录1 BOOT引脚配置和下载说明2 关于串口下载方式3 关于一按复位就跑代码4 关于下载调试速度5 关于三种启动方式5.1 FLASH启动5.2 系统存储器器启动5.3 SRAM启动6 关于程序的三种下载方式1 BOOT引脚配置和下载说明 BOOT0BOOT1程序运行ST-Link下载串口下载启动说明xx无0x√√用…...

基础01-ajax fetch axios 的区别

ajax fetch axios 的区别 题目 ajax fetch axios 的区别 分析 三者根本没有可比性&#xff0c;不要被题目搞混了。要说出他们的本质 传统 ajax AJAX &#xff08;几个单词首字母&#xff0c;按规范应该大写&#xff09; - Asynchronous JavaScript and XML&#xff08;异…...

Android Execution failed for task ‘:app:mergeDebugJavaResource

错误提示 FAILURE: Build failed with an exception.* What went wrong: Execution failed for task :app:mergeDebugJavaResource. > A failure occurred while executing com.android.build.gradle.internal.tasks.MergeJavaResWorkAction> 2 files found with path k…...

LogExpert实战指南:5大核心功能深度探索Windows日志分析高效方案

LogExpert实战指南&#xff1a;5大核心功能深度探索Windows日志分析高效方案 【免费下载链接】LogExpert Windows tail program and log file analyzer. 项目地址: https://gitcode.com/gh_mirrors/lo/LogExpert LogExpert是一款专为Windows平台设计的图形化日志分析工具…...

告别网课低效循环:这款开源工具如何让学习时间减半

告别网课低效循环&#xff1a;这款开源工具如何让学习时间减半 【免费下载链接】mooc-assistant 慕课助手 浏览器插件(Chrome/Firefox/Opera) 项目地址: https://gitcode.com/gh_mirrors/mo/mooc-assistant 你是否曾在深夜对着电脑屏幕&#xff0c;一遍遍重复着相同的手…...

StreamFX终极指南:如何用免费插件让OBS直播画面秒变专业

StreamFX终极指南&#xff1a;如何用免费插件让OBS直播画面秒变专业 【免费下载链接】obs-StreamFX StreamFX is a plugin for OBS Studio which adds many new effects, filters, sources, transitions and encoders! Be it 3D Transform, Blur, complex Masking, or even cus…...

Go并发读写竞争漏洞:结构体赋值引发的密钥泄露

1. 这不是段子&#xff0c;是真实发生的“裸奔”现场CVE-2026-27944——这个编号刚在NVD&#xff08;美国国家漏洞库&#xff09;公开时&#xff0c;我正盯着一台生产环境的API网关日志发呆。它没报错&#xff0c;没超时&#xff0c;但每分钟有3700次请求在返回200的同时&#…...

Thorium浏览器深度解析:如何通过编译优化实现300%性能提升的技术革命

Thorium浏览器深度解析&#xff1a;如何通过编译优化实现300%性能提升的技术革命 【免费下载链接】thorium Chromium fork named after radioactive element No. 90. Source code and Linux releases. Windows/MacOS/ARM builds served in different repos, links are towards …...

DS4Windows:让PS4手柄在Windows电脑上焕发新生!5个超实用功能解锁游戏新境界

DS4Windows&#xff1a;让PS4手柄在Windows电脑上焕发新生&#xff01;5个超实用功能解锁游戏新境界 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows 还在为PC游戏不支持PS4手柄而烦恼吗&a…...

构建高可用在线机器学习推理系统:分层回退架构设计与金融风控实践

1. 项目概述与核心挑战在金融科技领域&#xff0c;尤其是在线支付和信贷审批场景&#xff0c;机器学习模型已经从后台的分析工具&#xff0c;演变为实时业务决策的核心引擎。想象一下&#xff0c;当用户点击“确认支付”的瞬间&#xff0c;一个复杂的风控模型必须在几百毫秒内&…...

RAG:终结AI“一本正经胡说八道”,让AI回答问题不再答非所问!

本文用通俗易懂的方式解释了RAG技术&#xff0c;即“检索增强生成”&#xff0c;它通过为AI构建专属知识库&#xff0c;在回答问题时先检索相关信息再生成答案&#xff0c;有效解决AI“答非所问”和“幻觉”问题。文章详细介绍了RAG的工作原理、核心价值及实用场景&#xff0c;…...

突破小红书反爬:5个User-Agent伪装策略与实战指南

突破小红书反爬&#xff1a;5个User-Agent伪装策略与实战指南 【免费下载链接】XHS-Downloader 小红书&#xff08;XiaoHongShu、RedNote&#xff09;链接提取/作品采集工具&#xff1a;提取账号发布、收藏、点赞、专辑作品链接&#xff1b;提取搜索结果作品、用户链接&#xf…...

茉莉花插件:3分钟搞定Zotero中文文献管理的完整指南

茉莉花插件&#xff1a;3分钟搞定Zotero中文文献管理的完整指南 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件&#xff0c;用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/jasminum 还在为Zotero无法…...