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 方法,在方法中编写自己的业务代码 Component public class LoginInterceptor implements HandlerInterceptor {/*** 此方法返回一个 boolean,如果为 true …...
MySQL——插入加锁/唯一索引插入死锁/批量插入效率
本篇主要介绍MySQL跟加锁相关的一些概念、MySQL执行插入Insert时的加锁过程、唯一索引下批量插入可能导致的死锁情况,以及分别从业务角度和MySQL配置角度介绍提升批量插入的效率的方法;MySQL跟加锁相关的一些概念在介绍MySQL执行插入的加锁过程之前&…...
【专项训练】数组、链表
数组array: list = []链表linked list # Definition for singly-linked list. class ListNode:def __init__(self, x):self.val = xself.next =...
基于Jeecgboot前后端分离的ERP系统开发代码生成(六)
商品信息原先生成的不符合要求,重新生成,包括一个附表商品价格信息表 一、采用TAB主题一对多的模式 因为主键,在online表单配置是灰的,所以不能进行外键管理,只能通过下面数据库进行关联录入,否则online界面…...
什么?同步代码块失效了?-- 自定义类加载器引起的问题
一、背景 最近编码过程中遇到了一个非常奇怪的问题,基于单例对象的同步代码块似乎失效了,百思不得其姐。 下面给出模拟过程和最终的结论。 二、场景描述和模拟 2.1 现象描述 Database实现单例,在 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共享设置(配置文件详解)1.5 访问共享目录1. windows访问2. linux客…...
深入分析@Configuration源码
文章目录一、源码时序图1. 注册ConfigurationClassPostProcessor流程源码时序图2. 注册ConfigurationAnnotationConfig流程源码时序图3. 实例化流程源码时序图二、源码解析1. 注册ConfigurationClassPostProcessor流程源码解析(1)运行案例程序启动类Conf…...
Unity 代码优化 内存管理优化
项目遇到了卡顿的情况 仔细检查了代码没检查出有误的地方 仔细的总结了一下可以优化的东西 解决了卡顿 记录一下 1 协程 项目之前写的关于倒计时之类的东西 都是开了个协程 虽然协程是消耗很小的线程 , 可是还是有额外消耗 而且 有很多用携程来检测销毁预制体的操作 也都放到U…...
设计模式~门面(外观)模式(Facade)-08
目录 (1)优点 (2)缺点 (3)使用场景 (4)注意事项: (5)应用实例: (6)源码中的经典应用 代码 外观模式&am…...
C++面向对象编程之一:封装
C面向对象编程三大特性为:封装,继承,多态。C认为万事万物皆为对象,对象有属性和行为。比如:游戏里的地图场景可以看作是长方形对象,属性场景id,有长,有宽,可能有NPC&…...
IDEA插件系列(3):Maven Helper插件
一、引言在写Java代码的时候,我们可能会出现Jar包的冲突的问题,这时候就需要我们去解决依赖冲突了,而解决依赖冲突就需要先找到是那些依赖发生了冲突,当项目比较小的时候,还比较依靠IEDA的【Diagrams】查看依赖关系&am…...
SAP 更改物料基本计量单位
前言部分 在SAP中物料创建后,一旦发生业务,其基本计量单位便很难修改。由于单位无法满足业务要求,往往会要求新建一个物料替代旧物料。这时候除了要将旧物料上所有的未清业务删除外,还需要替换工艺与BOM中的旧物料。特别是当出现旧…...
蓝桥web基础知识学习
HTMLCSS 知识点重要指数HTML 基础标签🌟🌟🌟🌟🌟HTML5 新特性🌟🌟🌟🌟🌟HTML5 本地存储🌟🌟🌟🌟CSS 基础语法…...
Python+ChatGPT制作一个AI实用百宝箱
目录一、注册OpenAI二、搭建网站及其框架三、AI聊天机器人四、AI绘画机器人ChatGPT 最近在互联网掀起了一阵热潮,其高度智能化的功能能够给我们现实生活带来诸多的便利,可以帮助你写文章、写报告、写周报、做表格、做策划甚至还会写代码。只要与文字相关…...
Python中格式化字符串输出的4种方式
Python格式化字符串的4中方式 一、%号 二、str.format(args) 三、f-Strings 四、标准库模板 五、总结四种方式的应用场景’ 一、%号占位符 这是一种引入最早的一种,也是比较容易理解的一种方式.使用方式为: 1、格式化字符串中变化的部分使用占位符 2、…...
C#基础教程15 枚举与类
文章目录 C# 枚举(Enum)声明 enum 变量C# 类(Class)类的定义成员函数和封装C# 中的构造函数关键字 staticC# 枚举(Enum) 枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。 C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。 声明 enum 变…...
三步 让你的 vscode 自动编译ts文件
三步让你的 vscode 自动编译ts文件 TypeScript环境安装与如何在vscode实现自动编译ts文件? 文章目录三步让你的 vscode 自动编译ts文件前提条件环境安装自动编译运行监视任务时报错?前提条件 安装 node 环境 环境安装 tsc 作用:负责将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 的区别 分析 三者根本没有可比性,不要被题目搞混了。要说出他们的本质 传统 ajax AJAX (几个单词首字母,按规范应该大写) - Asynchronous JavaScript and XML(异…...
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…...
Hackintool终极指南:三步解决黑苹果显卡、音频和USB配置难题
Hackintool终极指南:三步解决黑苹果显卡、音频和USB配置难题 【免费下载链接】Hackintool The Swiss army knife of vanilla Hackintoshing 项目地址: https://gitcode.com/gh_mirrors/ha/Hackintool 还在为黑苹果配置而烦恼吗?显卡驱动不工作、音…...
【实战指南】解决Qt平台插件加载失败:从环境变量到PyQt5重装的完整方案
1. 遇到Qt平台插件加载失败?别慌,先看懂报错信息 最近在Windows上跑labelimg标注工具时,突然弹出一个让人头疼的错误: qt.qpa.plugin: Could not load the Qt platform plugin "windows" in "" even though…...
程序员副业变现全攻略
CSDN程序员副业图谱技术文章大纲副业方向分类技术变现类:外包开发、技术咨询、代码审核内容创作类:技术博客、视频教程、电子书编写产品开发类:独立应用、开源项目、插件工具教育培训类:在线课程、一对一辅导、技术直播技术栈与工…...
Beyond Compare 5密钥生成终极指南:轻松解决评估模式错误
Beyond Compare 5密钥生成终极指南:轻松解决评估模式错误 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 你是否曾遇到Beyond Compare 5弹出"评估模式错误"的困扰…...
医疗AI智能体:从数据到关怀人文设计:告别冰冷精准,构建有温度的诊疗交互.131
一、智能体的人文设计医疗AI智能体以大模型为核心,串联医学知识图谱、实体识别模块、风险评估模块、话术生成模块、伦理审核模块五大核心组件,最终实现精准医学判断 人性化交互的双重目标。而在医疗场景中,用户的核心需求从来不是单纯的数据…...
3个核心模块揭秘:Python量化投资如何免费获取通达信专业数据
3个核心模块揭秘:Python量化投资如何免费获取通达信专业数据 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 你是否在量化投资中为数据获取而烦恼?商业接口太贵,…...
Pixel Couplet Gen效果展示:抽象门神像素方块+动态卷轴交互演示
Pixel Couplet Gen效果展示:抽象门神像素方块动态卷轴交互演示 1. 项目概览 Pixel Couplet Gen是一款融合传统春节文化与现代像素艺术风格的AI春联生成器。通过ModelScope大模型驱动,将传统春联创作转化为充满游戏感的数字体验。 核心特点:…...
5分钟上手Godot 4.0地形系统:用AutoTile实现像素风草地自动拼接(含Layer新功能演示)
5分钟掌握Godot 4.0地形系统:用AutoTile实现像素风无缝拼接 在像素风格游戏开发中,地形拼接一直是让开发者头疼的问题——如何让草地、石块、沙土等元素自然过渡?传统方案往往需要手动放置大量图块或编写复杂逻辑。Godot 4.0的TileMap系统带来…...
GraphSAGE实战:用PyTorch Geometric实现工业级节点分类(含邻居采样优化技巧)
GraphSAGE工业级实战:PyTorch Geometric实现与亿级节点优化指南 当电商平台的日活用户突破千万量级时,传统的用户行为预测模型开始显露出明显的局限性。静态的特征工程无法捕捉用户间复杂的交互关系,而基于全图计算的GNN方法又难以应对实时更…...
Win11共享打印机连接失败?绕过安全策略的终极指南
1. Win11共享打印机连接失败的真相 最近帮朋友处理Win11共享打印机的问题时,发现这个看似简单的操作居然能卡住这么多人。明明按照传统方法一步步操作,却总是提示各种错误。其实这背后是微软在Win11 22H2版本后引入的新安全策略在作祟 - 他们默认关闭了S…...
