SpringBoot统一功能处理,拦截器,统一数据格式,捕捉异常

 

目录

拦截器:是Spring框架提供的核心功能之一,主要用来拦截用户的请求,在指定方法前后,根据业务需要执行预先设定的代码:

自定义拦截器

统一数据格式,要包含状态码,错误信息​编辑

出现针对String类型的错误​​​​​​​

为什么要统一

统一功能来实现捕捉到异常。​编辑

@ControllerAdvice源码分析


数据结构面试:HashMap,ConcurrentHashMap,ThreadLocal要看(建议看源码)

网络:TCP,UDP,HTTP

并发编程:线程创建方式,线程的状态,锁,synchronized,volatile

数据库 基本操作,关键字,

JVM-内存结构,GC

Linux

引入拦截器的原因。

拦截器:是Spring框架提供的核心功能之一,主要用来拦截用户的请求,在指定方法前后,根据业务需要执行预先设定的代码:

(指定在哪些方法前后执行)

JDK17把之前Java的包都换为Jakarta。

指定方法:——指我们登录验证的某些方法(比如图书的增删改查),怎样可以不用动太多代码,实现这个功能

预先设定的代码:对用户是否登录进行验证

拦截器的实现分为两步:(作用维度以url为维度)

1.定义一个拦截器

2.把拦截器注册到项目中

自定义拦截器:实现HandlerInterceptor接口,并重写所有方法

拦截器的定义

自定义拦截器

/* 一级路径    能匹配/user,/book,/login,不能匹配/user/login

/** 任意级路径 能匹配 /user,/user/login,/book

/book/*      /book下的一级路径 能匹配/book/addBook,不能匹配/book/addBook

/book/**    /book下的任意级路径     能匹配/book,/book/addBook,/book/addBook/2...。

正常工作方式

用户调用->(拦截器)->控制器层(Controller)->调用服务层(Service)->数据持久层(Mapper)->数据库

1.添加拦截器后, 执⾏Controller的⽅法之前, 请求会先被拦截器拦截住. 执⾏ preHandle() ⽅法, 

这个⽅法需要返回⼀个布尔类型的值. 如果返回true, 就表⽰放⾏本次操作, 继续访问controller中的 

⽅法. 如果返回false,则不会放⾏(controller中的⽅法也不会执⾏).

2. controller当中的⽅法执⾏完毕后,再回过来执⾏ postHandle() 这个⽅法以及

afterCompletion() ⽅法,执⾏完毕之后,最终给浏览器响应数据

DispatcherServlet(Dispatcher调度器,servlet生命周期)​​​​​​​​​​​​​​

源码环节

适配器模式和门面模式区别

1.适配器模式:是适配两者之间的差异(为了补救设计上的缺陷,应用这种模式也是无心之举),门面模式是统合了底层系统(我认为一个像是七巧板把两个不同的连接起来,门面模式就像是给他装了一个套,它里面不变,只是说可以调用他们两个)我们通过外面的套来调用里面。

统一数据格式,要包含状态码,错误信息


supports⽅法: 判断是否要执⾏beforeBodyWrite⽅法. true为执⾏, false不执⾏. 通过该⽅法可以 选择哪些类或哪些⽅法的response要进⾏处理, 其他的不进⾏处理.

beforeBodyWrite⽅法: 对response⽅法进⾏具体操作处理

出现针对String类型的错误​​​​​​​

 快速⼊⻔ 统⼀的数据返回格式使⽤ @ControllerAdvice 和 ResponseBodyAdvice 的⽅式实现
@ControllerAdvice 表⽰控制器通知类 添加类 ResponseAdvice , 实现 ResponseBodyAdvice 接⼝, 并在类上添加
@ControllerAdvice 注解
import com.example.demo.model.Result;
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;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
 }
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 
MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest 
request, ServerHttpResponse response) {
return Result.success(body);
 }
} 

解决方法:


public class TestController {
@RequestMapping("/t1")
public String t1(){
return "t1";
 }
@RequestMapping("/t2")
public boolean t2(){
return true;
 }
@RequestMapping("/t3")
public Integer t3(){
return 200;
 }
} 
解决⽅案:
import com.example.demo.model.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
private static ObjectMapper mapper = new ObjectMapper();
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
 }
@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 
MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest 
request, ServerHttpResponse response) {
//如果返回结果为String类型, 使⽤SpringBoot内置提供的Jackson来实现信息的序列化
if (body instanceof String){
return mapper.writeValueAsString(Result.success(body));
 }
return Result.success(body);
 }
}

为什么会有这样的错误呢?

SpringMVC默认会注册⼀些⾃带的 HttpMessageConverter (从先后顺序排列分别为

ByteArrayHttpMessageConverter ,

StringHttpMessageConverter , SourceHttpMessageConverter ,

SourceHttpMessageConverter , AllEncompassingFormHttpMessageConverter )

AllEncompassingFormHttpMessageConverter 会根据项⽬依赖情况 添加对应的

HttpMessageConverter

在依赖中引⼊jackson包后,容器会把 MappingJackson2HttpMessageConverter ⾃动注册到

messageConverters 链的末尾.

Spring会根据返回的数据类型, 从 messageConverters 链选择合适的

HttpMessageConverter . 

当返回的数据是⾮字符串时, 使⽤的 MappingJackson2HttpMessageConverter 写⼊返回对象. 

当返回的数据是字符串时, StringHttpMessageConverter 会先被遍历到,这时会认为

StringHttpMessageConverter 可以使⽤

在 ((HttpMessageConverter) converter).write(body, selectedMediaType, 

outputMessage) 的处理中, 调⽤⽗类的write⽅法 

由于 StringHttpMessageConverter 重写了addDefaultHeaders⽅法, 所以会执⾏⼦类的⽅法

然⽽⼦类 StringHttpMessageConverter 的addDefaultHeaders⽅法定义接收参数为String, 此 

时t为Result类型, 所以出现类型不匹配"Result cannot be cast to java.lang.String"的异常

​​​​​​​最终

为什么要统一

1. ⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据

2. 降低前端程序员和后端程序员的沟通成本, 按照某个格式实现就可以了, 因为所有接⼝都是这样返回 

的.

3. 有利于项⽬统⼀数据的维护和修改.

4. 有利于后端技术部⻔的统⼀规范的标准制定, 不会出现稀奇古怪的返回内容.

统一功能来实现捕捉到异常。

Spring的代码在书写统一的过程中,不按照顺序。

捕捉异常的时候,看他报什么异常,最贴近哪个,那么就是哪个

不加ResponseBody -她就会把下面那个异常当成一条数据

package com.example.demo.config;

import com.example.demo.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@Slf4j
@ResponseBody
@ControllerAdvice
public class ErrorHandler {
    @ExceptionHandler
    public Result exception(Exception e){
        log.error("发生异常e{}",e);
        return Result.fail("内部错误");
    }
    @ExceptionHandler
    public Result exception(NullPointerException e){
        log.info("发生异常");
        return Result.fail("NullPointerException异常,请联系管理员");
    }
    @ExceptionHandler
    public Result exception(ArithmeticException e){
        log.info("发生异常");
        return Result.fail("ArithmeticException 异常,请联系管理员");
    }



}

Spring容器最开始启动时,会进行初始化的工作,其中会对异常进行处理,当异常项有多个匹配的时候,Spring会对其顺序依次排,找出最符合的报异常。

​​​​​​​

@ControllerAdvice源码分析

述源码可以看出 @ControllerAdvice 派⽣于 @Component 组件, 这也就是为什么没有五 

⼤注解, ControllerAdvice 就⽣效的原因

当Controller抛出异常时, DispatcherServlet 通过

ExceptionHandlerExceptionResolver 来解析异常,⽽

ExceptionHandlerExceptionResolver ⼜通过 ExceptionHandlerMethodResolver 来解析异常, ExceptionHandlerMethodResolver 最终解析异常找到适⽤的@ExceptionHandler标注

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ssl数字证书是什么

SSL证书是一种数字证书,用于在网络传输中提供加密和身份验证功能,从而保护数据的安全性和完整性。正规的SSL证书大多是由由权威的证书颁发机构(CA)颁发的,例如Certum、Digicert、Sectigo等,它们颁发的SSL数…

C盘文件详解

C盘是指电脑硬盘主分区之一,一般用于储存或安装系统使用。大部分C盘内文件主要由Windows、Program Files等系统文件夹组成。文件夹作用:文件夹是用来组织和管理磁盘文件的一种数据结构。 $WinREAgent文件夹,是在系统更新或升级过程中创建的文…

腾讯主导制定全球首个车载小程序国际标准,助力车载应用生态发展

2024年1月,国际电信联盟标准部门(ITU-T)正式发布了由腾讯主导制定的《F.749.8 In-vehicle multimedia applets: Framework and functional requirements》(车载多媒体小程序框架和技术需求)国际标准。 这是全球首个由中国企业主导制定的车载小…

element-ui icon 组件源码分享

今日简单分享 element-ui 源码中的 icon 组件,主要从以下两个方面来分享: 一、源码中 icon 设计思想是什么呢?主要从页面结构、数据、 icon 样式三个方面来分享。 1.1 源码中 icon 组件的页面结构,可以在 package 目录下找到 ico…

【ADI 知识库】X 波段相控阵开发平台 硬件 2

ADAR1000EVAL1Z (Stingray) ADAR1000-EVAL1Z评估板是一款模拟波束成形前端,设计用于测试ADAR1000和ADTR1107的性能。ADAR1000 是一款 8 GHz 至 16 GHz、4 通道、X 波段和 Ku 波段波束成形器 IC。ADTR1107是 6 GHz 至 18 GHz 前端发送/接收模块。 ADAR1000-EVAL1Z板…

React + react-device-detect 实现设备特定的渲染

当构建响应式网页应用时,了解用户正在使用的设备类型(如手机、平板或桌面)可以帮助我们提供更优化的用户体验。本文将介绍如何在 React 项目中使用 react-device-detect 库来检测设备类型,并根据不同的设备显示不同的组件或样式。…

Python开源项目周排行 2024年第3周

ython 趋势周报,按周浏览往期 GitHub,Gitee 等最热门的Python开源项目,入选的项目主要参考GitHub Trending,部分参考了Gitee和其他。排名不分先后,都是当周相对热门的项目。 入选公式=70%GitHub Trending20%Gitee10%其他 关注微…

vtkNIFTIImageReader读写方位以及原点信息

使用vtkNIFTIImageReader读取体数据为vtkImageData时只会携带spacing信息&#xff0c;方向和原点信息不会写入&#xff0c;需要获取QFormMatrix进行解析。 1、方向及原点读取 vtkSmartPointer<vtkNIFTIImageReader> niiReader vtkSmartPointer<vtkNIFTIImageReader&…

C# winform 多语言(json)方式实现

前后对比 使用nuget json工具包1.总体思路 创建对应的json字典对照表 { "测试":"Test", "语言":"Language", "设置":"Set", "中文(默认)":"Chinese (default)", "英文":"E…

el-button按钮点击不起作用,被遮盖

1.图示 2.解决 原因&#xff1a;按钮被tabs遮盖 解决&#xff1a;先relative再absolute即可&#xff0c;如下

C++开发基础之循环链表详解含示例

1. 引言 循环链表的概念和特点 循环链表是一种链表的变体&#xff0c;它与普通链表最大的不同是&#xff1a;在循环链表中&#xff0c;最后一个节点的指针不是NULL&#xff0c;而是指向头节点&#xff0c;形成了一个环。这种特殊结构使得循环链表中的数据可以像环一样循环访问…

【日常聊聊】开源软件影响力

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 方向一&#xff1a;开源软件如何推动技术创新 方向二&#xff1a;开源软件的商业模式 方向三&#xff1a;开源软件的安全风险 方…

Java中使用StopWatch实现代码块耗时统计/计时某段代码执行

场景 Java实战-基于JDK的LRU算法实现、优雅的实现代码耗时统计(Spring AOP、AutoCloseable方式)&#xff1a; Java实战-基于JDK的LRU算法实现、优雅的实现代码耗时统计(Spring AOP、AutoCloseable方式)_lru 算法 jdk-CSDN博客 上面讲了统计方法的耗时&#xff0c;实现和使用…

单机搭建hadoop环境(包括hdfs、yarn、hive)

单机可以搭建伪分布式hadoop环境&#xff0c;用来测试和开发使用&#xff0c;hadoop包括&#xff1a; hdfs服务器 yarn服务器&#xff0c;yarn的前提是hdfs服务器&#xff0c; 在前面两个的基础上&#xff0c;课可以搭建hive服务器&#xff0c;不过hive不属于hadoop的必须部…

林浩然与杨凌芸的Java奇缘:静态关键字的恋爱三部曲

林浩然与杨凌芸的Java奇缘&#xff1a;静态关键字的恋爱三部曲 Lin Haoran and Yang Lingyun’s Java Romance: The Trilogy of Love with the Static Keyword 在编程世界里&#xff0c;有一个名叫林浩然的程序员&#xff0c;他风度翩翩&#xff0c;思维敏捷&#xff0c;对Java…

yo!这里是c++IO流相关介绍

目录 前言 C语言的输入输出 CIO流基本介绍 流的概念 IO流类库 iostream fstream stringstream 后记 前言 学过C语言的输入输出相关知识点的童鞋应该多多少少会觉得有些许麻烦&#xff0c;反正我就是这么觉得的&#xff0c;scanf、printf等函数不仅数量众多&#xff0c…

金三银四_程序员怎么写简历_写简历网站

你们在制作简历时,是不是基本只关注两件事:简历模板,还有基本信息的填写。 当你再次坐下来更新你的简历时,可能会发现自己不自觉地选择了那个“看起来最好看的模板”,填写基本信息,却没有深入思考如何使简历更具吸引力。这其实是一个普遍现象:许多求职者仍停留在传统简历…

【Unity3D小技巧】Unity3D中UI控制解决方案

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中总是会控制UI界面&#xff0c;如何优雅的控制UI界面是…

12.1 主成分分析原理(PCA)

主成分分析步骤如下&#xff1a; 设有条维数据 1. 将原始数据按列组成行列矩阵 &#xff1b; 2. 将矩阵 的每一行进行零均值化&#xff1b; 3. 求出协方差矩阵&#xff1b; 4. 求出协方差矩阵的特征值及对应的特征向量&#xff1b; 5. 将特征向量按对应特征值大小从上到…

富文本编辑器CKEditor4简单使用-04(跟源码设置image2插件图片的默认宽高等相关配置)

富文本编辑器CKEditor4简单使用-04&#xff08;跟源码设置image2插件图片的默认宽高等相关配置&#xff09; 1. 前言1.1 CKEditor4快速上手 2. CKEditor4的一般配置2.1 工具栏相关2.2 插件相关2.3 设置界面宽高等 3. CKEditor4的图片相关配置3.1 关于增强的图像插件的必要配置3…