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

【Spring AOP】如何统一“拦截器校验、数据格式返回、异常返回”处理?

目录

一、Spring  拦截器

1.1、背景

1.2、实现步骤

1.3、拦截原理

二、 统一url前缀路径

2.1、方法一:在系统的配置文件中设置

2.2、方法二:在 application.properies 中配置

三、统一异常处理

四、统一返回数据返回格式处理

4.1、背景

4.2、具体实现


一、Spring  拦截器


1.1、背景

在原生的 Spring AOP 中实现统一的拦截的难点在于:1.定义拦截规则(表达式)很难,2.在切面类中拿到 HttpSession 比较难;如何解决这两个难点呢?使用拦截器!

1.2、实现步骤

实现一个普通的拦截器关键在于以下两步:

  1. 实现 HandlerInterceptor 接口,重写 preHeadler 方法,在方法中编写自己的业务代码。
  2. 将拦截器添加到配置文件中,设置拦截规则。

具体的,首先步骤一,例如要实现一个用户登录判断,就需要创建一个类,这里起名叫LoginInterceptor 类,实现 HandlerInterceptor 接口,重写 preHeadler 方法(此方法返回的是以个 boolean 类型,如果为 true 表示验证成功,可以继续执行后面的流程,若是 false 表示验证失败,后面的流程就不执行了),通过是否可以获取到 Session 信息判断用户是否已经登陆,来返回 true 或 false。

a)实现 HandlerInterceptor 接口,重写 preHeadler 方法,如下代码:

import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;//登录拦截器
public class LoginInterceptor implements HandlerInterceptor {/*** 此方法返回一个 boolean,若为 true 表示验证成功,否则验证失败,后面的流程不能执行了* @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);if(session != null && session.getAttribute("userinfo") != null) {//说明用户已经登陆return true;}//可以调整登录页面,或者 返回一个 401/403 没有权限response.sendRedirect("/login.html");return false;}
}

b)将拦截器添加到配置文件中,设置拦截规则

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 AppConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //连接所有请求,值得注意的是,这里不能只写一个 *,一个 * 表示一级路径.excludePathPatterns("/user/login") //不拦截的 url.excludePathPatterns("/user/reg").excludePathPatterns("/**/*.html"); //不拦截所有的页面}
}

注意:

addPathPatterns:表示需要拦截的 URL,“**”表示拦截任意⽅法(也就是所有⽅法)。 excludePathPatterns:表示需要排除的 URL。

说明:以上拦截规则可以拦截此项⽬中的使⽤ URL,包括静态⽂件(图⽚⽂件、JS 和 CSS 等⽂件)

1.3、拦截原理

二、 统一url前缀路径


2.1、方法一:在系统的配置文件中设置

具体的,重写 WebMvcConfigurer 接口下的 configurePathMatch 方法,例如修改所有请求url添加前缀 /zhangsan ,如下代码:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class AppConfig implements WebMvcConfigurer {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {configurer.addPathPrefix("/zhangsan", c -> true);}}

2.2、方法二:在 application.properies 中配置

例如修改所有请求url添加前缀 /zhangsan,如下代码:

server.servlet.context-path=/zhangsan

三、统一异常处理


统一异常处理是通过如下两个注解结合实现的:

  • @ControllerAdvice:表示控制器通知类。
  • @ExceptionHandler:表示异常处理器。

两个结合表示出现异常的时候执行某个通知方法,具体的步骤如下:

  1. 创建一个类,标识上 @ControllerAdvice;
  2. 在方法上添加 @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 MyExHandler {/*** 拦截所有的空指针异常,进行统一的数据返回* @param e* @return*/@ExceptionHandler(Exception.class) //这里也可以根据实际情况,填写不同的异常public HashMap<String, Object> nullException(NullPointerException e) {HashMap<String, Object> reslut = new HashMap<>();reslut.put("code", "-1");reslut.put("msg", "空指针异常" + e.getMessage());reslut.put("data", null);//这里返回 HashMap ,就相当于项前端返回了一个 JSON 格式的数据return reslut;}}

四、统一返回数据返回格式处理


4.1、背景

为什么要统一数据返回格式处理?例如以下几个原因:

  • 方便前端程序员更好的接收和解析后端返回的数据;
  • 降低约定前后端交互接口的成本,按照某种格式实现即可,因为所有的接口都是这样返回的。
  • 有利于项目的统一数据的维护和修改。

4.2、具体实现

统一数据格式返回的实现需要以下两个步骤:

  1. 创建一个类,并添加 @ControllerAdvice。
  2. 实现 ResponseBodyAdvice 接口,重写 supports 和  beforeBodyWrite。

Ps:

1、 supports 方法不用编写业务逻辑,而是像一个控制器一样,返回 true 则执行 beforeBodyWrite 方法,反之则不执行。

2、beforeBodyWrite 方法就是用来实现统一对象的。

具体的如下:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
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 ResponseAdvice implements ResponseBodyAdvice {//将 java 对象转化成 JSON 格式@Autowiredprivate ObjectMapper objectMapper;/*** 此方法返回 true 则执行下面的 beforeBodyWrite 方法,反之则不执行* @param returnType* @param converterType* @return*/@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {HashMap<String, Object> result = new HashMap<>();result.put("code", 200);result.put("msg", "");result.put("data",body);// 这里需要进行特殊处理,因为 String 在转换的时候报错if(body instanceof String) {try {return objectMapper.writeValueAsString(result);} catch (JsonProcessingException e) {e.printStackTrace();}}return result;}
}

代码中为什么要进行特殊处理?(最易出错!)

在 java 程序中, String 是一个最特殊的类型(既不是基础类型也不是对象),并且在重写方法时也很特殊,除了 String 其他的都是用一个格式化工具,而 String 用的是自己的一套格式化工具,因此在转换成 HashMap 的时候还没有被加载好,而其他的转换器已经加载好了,最后就会引发如下异常:

因此就要判断 body 是否为 String ,若为 String 类型,就要进行特殊处理,使用 JSON 的writeValueAsString 方法将 Java 对象转换成 JSON 格式再返回。

 

 

相关文章:

【Spring AOP】如何统一“拦截器校验、数据格式返回、异常返回”处理?

目录 一、Spring 拦截器 1.1、背景 1.2、实现步骤 1.3、拦截原理 二、 统一url前缀路径 2.1、方法一&#xff1a;在系统的配置文件中设置 2.2、方法二&#xff1a;在 application.properies 中配置 三、统一异常处理 四、统一返回数据返回格式处理 4.1、背景 4.2、…...

规划数据指标体系方法(下)——新海盗模型

前面已经跟大家分享了规划数据指标体系的两种方法—— OSM 和 UJM 模型&#xff0c;分别从目标-策略以及用户旅途的角度阐述了规划数据指标体系的过程。今天我来跟大家分享最后一种规划数据指标体系的方法——新海盗模型。 了解新海盗模型 海盗模型&#xff0c;即 AARRR 模型&…...

UML学习备忘录

UML学习备忘录 UML 全称是 Unified Modeling Language&#xff08;统一建模语言&#xff09;&#xff0c;它以图形的方式来描述软件的概念。它的特点是简单、统一、图形化、能表达软件设计中的动态与静态信息。UML的本质就是为了交流。 UML的概念包括了UML语义&#xff08;Se…...

Vue3手写分页在分页的基础上用到Pagination 分页组件

近期有个项目要用到分页组件&#xff0c;但是内容不是表格&#xff0c;所以自己就研究了一下在Pagination 分页组件的基础上手写了分页 效果图&#xff1a; 目录 一、先声明几个变量用来定义第几页&#xff0c;每页多少条&#xff0c;总页数。 二、然后封装一个函数方便以后…...

冥想第七百二十四天

1.今天感谢徐工的款待&#xff0c;请教了学习日语的一个方法就是把听力复述出来。 2.今天感觉运动量特别少&#xff0c;于是就下班跑了6公里&#xff0c;状态良好。 3.觉得出来出差真的好轻松&#xff0c;有点不适应了。感谢生活给我的奖励 好幸福呀。 4.感谢父母&#xff0c;感…...

Jenkins+Docker自动化部署项目

看到了一篇文章&#xff0c;实操一下自动部署的感觉。参看地址&#xff1a;原文 首先更新docker&#xff0c;我更新到了 [rootlocalhost springboot]# docker --version Docker version 23.0.1, build a5ee5b1跟新步骤&#xff1a; yum update#卸载旧版本 yum remove dock…...

TX2配置RealSense D455相机SDK和ros驱动

TX2配置RealSense D455相机SDK和ros驱动1 SDK安装2 RealSense-ros安装3 bug及解决3.1 realsense-viewer显示usb2.13.2 Could not found ddynamic_reconfigure折腾了两天终于把realsense的驱动装好了&#xff0c;尝试了命令安装&#xff0c;源码安装&#xff0c;前前后后搞了三遍…...

Sentinel架构篇 - 来源访问控制

来源访问控制&#xff08;黑白名单&#xff09; 概念 Sentinel 提供了黑白名单限制资源能否通过的功能。如果配置了白名单&#xff0c;则只有位于白名单的请求来源的对应的请求才能通过&#xff1b;如果配置了黑名单&#xff0c;则位于黑名单的请求来源对应的请求不能通过。 …...

多线程的Thread 类及方法

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;Java EE初阶&#x1f447; ✨每日一语&#xff1a;海压竹枝低复举&#xff0c;风吹山角晦还明。 目 录&#x1f332;一. 线程的复杂性&#x1f334;二. Thread 类及常见方法&#x1f4d5;2.1 Thread 的常见构…...

QT入门Item Views之QTreeView

目录 一、QTreeView界面相关 1、布局介绍 二、基本属性功能 1、设置单元格不能编辑 2、一次选中一个item 3、去掉鼠标移动到单元格上的虚线框 4、最后一列自适应 三、代码展示 1、创建模型&#xff0c;导入模型 2、 右键菜单栏 3、双…...

Servlet | Servlet简单入门——构建第一个Servlet项目

本专栏主要是记录学习JavaWeb中的Servlet相关知识点&#xff0c;如果刚开始学习Java的小伙伴可以点击下方连接查看专栏 本专栏地址&#xff1a;&#x1f525;Servlet Java入门篇&#xff1a; &#x1f525;Java基础学习篇 Java进阶学习篇&#xff08;持续更新中&#xff09;&am…...

Spring的IOC/DI,依赖注入的实现

Spring的IOC/DI&#xff0c;依赖注入的实现 https://download.csdn.net/download/weixin_41957626/87546826 资源地址 1.什么是Spring 1.1spring3 的体系结构图 图1 spring3的体系结构图 图2 spring4体系结构图 比较spring3的体系结构图&#xff0c;spring4去掉了spring3中的st…...

【tensorflow onnx】TensorFlow2导出ONNX及模型可视化教程

文章目录1 背景介绍2 实验环境3 tf2onnx工具介绍4 代码实操4.1 TensorFlow2与ONNX模型导出4.2 ONNX正确性验证4.3 TensorFlow2与ONNX的一致性检查4.4 多输入的情况4.5 设定输入/输出节点5 ONNX模型可视化6 ir_version和opset_version修改7 ONNX输入输出维度修改8 致谢原文来自于…...

天梯赛训练L1-013--L1-015

目录 1、L1-013 计算阶乘和 2、L1-014 简单题 3、L1-015 跟奥巴马一起画方块 1、L1-013 计算阶乘和 分数 10 题目详情 - L1-013 计算阶乘和 (pintia.cn) 对于给定的正整数N&#xff0c;需要你计算 S1!2!3!...N!。 输入格式&#xff1a; 输入在一行中给出一个不超过10的正…...

进程(操作系统408)

进程的概念和特征 概念&#xff1a; 进程的多个定义&#xff1a; 进程是程序的一次执行过程 进程是一个程序及其数据在处理机上顺序执行时所发生的活动 进程时具有独立功能的程序在一个数据集合上运行的过程&#xff0c;它是系统进行资源分配和调度的一个独立单位 上面所说…...

浅谈运维工程师的开发能力的培养

写在前面 本文已获得作者授权&#xff0c;作者的博客地址&#xff1a;https://www.cuiliangblog.cn/ 原文链接&#xff1a;浅谈运维工程师的开发能力的培养 一、运维工程师发展路线 1. 传统运维 侧重点是解决具体的问题。要求具备扎实的底层的知识储备&#xff0c;如网络、l…...

Netcode升级到1.2.0网络变量的变化的变化

Netcode升级到1.2.0网络变量的变化1 概述2 继承网络变量 NetworkVariable&#xff0c;派生类构造出错的问题2.1 代码描述2.2 问题记录2.3 解决办法&#xff1a;使用 NetworkVariable 即可3 网络变量 NetworkVariable 类的版本差异比较3.1 差异说明3.2 [1.0.2]版本的网络变量3.3…...

冥想第七百二十二天

1.周六去给朋友讲了一天的软件&#xff0c;给朋友带了2袋面包边&#xff0c;几袋方便面。感谢朋友的款待&#xff0c;做的蒸菜双拼&#xff0c;柠檬风爪&#xff0c;排骨汤&#xff0c;汤圆&#xff0c;牛肉&#xff0c;孜然回锅肉。 2.讲到下午五点&#xff0c;就回去了。感觉…...

AB测试——流程介绍(定义问题和指标选取)

前言&#xff1a; 作为AB测试的学习记录&#xff0c;本文主要介绍了AB测试的基本流程&#xff0c;以及指标类型和如何选取合适指标。 相关文章&#xff1a;AB测试——原理介绍 AB测试的基本流程是什么&#xff1f; AB测试&#xff08;也称为分流测试&#xff09;是一种常用的实…...

Linux(Centos)安装Minio集群

目录1&#xff1a;简介2&#xff1a;功能与集成3&#xff1a;架构4&#xff1a;搭建集群4.1&#xff1a;挂载磁盘4.1.1&#xff1a;要求4.1.2&#xff1a;创建挂载目录4.1.3&#xff1a;注意&#xff1a;需要将新建的目录挂在到对应的磁盘下,磁盘不挂载好&#xff0c;集群启动会…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...