Spring Boot——统一功能处理

news/2024/12/29 8:29:26/

1. 拦截器

拦截器主要用来拦截用户的请求,在指定方法前后,根据业务需要执行设定好的代码,也就是提前定义一些逻辑,在用户的请求响应前后执行,也可以在用户请求前阻止其执行,例如登录操作,只有登录成功之后用户才可以访问应用页面,这时就可以使用拦截器来拦截前端发来的请求,判断 session 中是否有登录用户的信息,如果没有就拦截,有的话就放行

1.1. 快速开始

首先需要定义拦截器,定义好之后注册并配置拦截器

自定义拦截器需要实现 HandlerInterceptor 接口,并重写它的方法

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("preHandle...");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("postHandle...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("afterCompletion...");}
}

注册配置拦截器需要实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法

@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor)//注册拦截器.addPathPatterns("/**")//对哪些路径生效.excludePathPatterns("/user/login");//对哪些路径不生效}
}

拦截路径

含义

举例

/*

一级路径

能匹配 /user,/book,/login,不能匹配 /user/login

/**

任意级路径

能匹配 /user,/user/login,/user/reg

/book/*

/book 下的一级路径

能匹配 /book/addBook,不能匹配 /book/addBook/1,/book

/book/**

/book 下的任意级路径

能匹配 /book,/book/addBook,/book/addBook/2,不能匹配 /user/login

2. 统一数据返回格式

以之前的图书管理系统为例,之前是手动封装了一层返回结果的

对于多个接口,如果都进行封装的话,肯定是非常麻烦的,所以就可以对返回格式进行统一

首先定义一个类,实现ResponseBodyAdvice接口并重写其中的方法,然后还要加上@ControllerAdvice注解来交给 Spring 管理

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;// false:不处理  true:处理}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {return Result.success(body);}
}

来介绍一下这两个方法:

supports:用于判断是否要对该方法的返回值进行处理,可以根据返回类型等条件来自定义,false:不处理 true:处理

beforeBodyWrite:在将返回值写入响应体之前调用,可以在这里对返回值进行统一的包装或者修改

上面的代码中表示所有方法都进行处理,处理的逻辑就是再封装一层之前定义的 Result 类成功的方法

响应的 body 中也封装好了

但是有一个问题,原来封装好的类型又封装了一层

就可以加个判断,如果已经是 Result 类型的就直接返回 body

除此之外,还有一个错误,当访问更新图书的接口之后报错了,而数据库中的信息还是成功修改了

具体的报错信息是类型匹配时的错误

在 Spring 中,返回值会经过 HttpMessageConverter 转换为 HTTP 响应的内容 ,字符串类型和非字符串类型的处理流程是不同的

对于 String 类型的返回值,Spring 使用 StringHttpMessageConverter 将其直接作为字符 串写入到 HTTP 响应中,而不会进一步封装或序列化。 非字符串类型的返回值会通过 MappingJackson2HttpMessageConverter 等转换器,序列化为 JSON 字符串。

此时 body 如果是字符串类型,StringHttpMessageConverter 会尝试直接将 Result.success(body) 转换为字符串,导致类型不匹配。

解决办法:

3. 统一异常处理

在之前写的代码中,每一个模块都有需要处理异常的地方,就可以把这些异常进行统一处理,统一异常处理是通过@ControllerAdvice注解和@ExceptionHandler注解来实现的

@Slf4j
@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {@ExceptionHandlerpublic Object handler(Exception e) {log.error("发生异常:e" + e);return Result.fail();}
}

来造几个常见的异常进行演示:

还可以通过重载的方式,细分具体发生的是什么异常,通过修改 fail 方法也可以自定义返回的错误信息

不过,在测试时发现最终返回的状态码是 200,这就不太合理

可以通过@ResponseStatus注解来设置返回的状态码,传入的参数必须是 HttpStatus 的常量


http://www.ppmy.cn/news/1559021.html

相关文章

FAISS进行高效的向量检索 原理详解

FAISS(Facebook AI Similarity Search)是由Facebook研发的一个用于高效相似性搜索和密集向量聚类的库。它特别适用于处理大规模向量数据库和提供快速的近邻搜索。FAISS高效的原因在于其专门的索引结构和优化的搜索算法。以下将详细解释FAISS的底层原理和…

【Sentinel】流控效果与热点参数限流

目录 1.流控效果 1.1.warm up 2.2.排队等待 1.3.总结 2.热点参数限流 2.1.全局参数限流 2.2.热点参数限流 2.3.案例 1.流控效果 在流控的高级选项中,还有一个流控效果选项: 流控效果是指请求达到流控阈值时应该采取的措施,包括三种&…

【Leetcode 每日一题】3159. 查询数组中元素的出现位置

问题背景 给你一个整数数组 n u m s nums nums,一个整数数组 q u e r i e s queries queries 和一个整数 x x x。 对于每个查询 q u e r i e s [ i ] queries[i] queries[i],你需要找到 n u m s nums nums 中第 q u e r i e s [ i ] queries[i] q…

Slater 条件与 KKT 条件

凸优化中的 Slater 条件与 KKT 条件详解 凸优化是数学优化中一类非常重要的问题,它在机器学习、信号处理、经济学等多个领域有广泛应用。本文将详细介绍凸优化中两个关键的理论工具:Slater 条件与Karush-Kuhn-Tucker (KKT) 条件。 一、凸优化问题的基本…

DP之背包基础

目录 DP简介 01背包问题 采药(01背包例题) 完全背包 疯狂的采药(完全背包例题) 背包变式 装箱问题 砝码称重 质数拆分 优化思考 DP简介 全称Dynamic Programming即动态规划 DP算法是解决多阶段决策过程最优化问题的一种常用方法。 多阶段决策过程是指这样一类特…

scala借阅图书保存记录(三)

BookDAO package org.app package daoimport models.BookModelimport scala.collection.mutable.ListBuffer//图书,数据操作 class BookDAO {//加载图书,从文件中读入def loadBooks(): ListBuffer[BookModel] {val books new ListBuffer[BookModel]()…

pycharm+anaconda创建项目

pycharmanaconda创建项目 安装: Windows下PythonPyCharm的安装步骤及PyCharm的使用-CSDN博客 详细Anaconda安装配置环境创建教程-CSDN博客 创建项目: 开始尝试新建一个项目吧! 选择好项目建设的文件夹 我的项目命名为:pyth…

QT-基础-1-Qt 中的字符串处理与常见数据类型

在 Qt 框架中,字符串处理是应用程序开发中不可或缺的一部分。Qt 提供了强大的 QString 类,以便于开发者处理文本数据,支持 Unicode 字符,并且拥有丰富的字符串操作方法。此外,Qt 还提供了其他相关类,如 QSt…