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 {@ExceptionHandlerpublic Result exception(Exception e){log.error("发生异常e{}",e);return Result.fail("内部错误");}@ExceptionHandlerpublic Result exception(NullPointerException e){log.info("发生异常");return Result.fail("NullPointerException异常,请联系管理员");}@ExceptionHandlerpublic Result exception(ArithmeticException e){log.info("发生异常");return Result.fail("ArithmeticException 异常,请联系管理员");}}

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

​​​​​​​

@ControllerAdvice源码分析

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

⼤注解, ControllerAdvice 就⽣效的原因

当Controller抛出异常时, DispatcherServlet 通过

ExceptionHandlerExceptionResolver 来解析异常,⽽

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux C | 网络编程】netstat 命令图文详解 | 查看网络连接、查看路由表、查看统计数据

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…

【AI数字人-论文】Geneface论文

文章目录 前言pipelineaudio-to-motionMotion domain adaptation可视化 Motion-to-imageHead-NeRFTorso-NeRF 结果对比 前言 语音驱动的说话人视频合成旨在根据一段输入的语音,合成对应的目标人脸说话视频。高质量的说话人视频需要满足两个目标: &#…

ele-h5项目使用vue3+vite开发:第二节、search 搜索框组件开发

如何设计一个组件 需求分析 布局 content left-iconbodyinput-controlright-iconaction 功能 使用 defineEmits 定义组件的事件 在组件的script setup 里如何定义事件 使用defineEmits&#xff08;&#xff09;定义先声明事件接口 <script setup lang"ts"> int…

儿童护眼台灯怎么选择?一文教你如何选择儿童护眼台灯

护眼台灯是家长最常为孩子购买的用品之一&#xff0c;但是大部分人对它的了解并不多&#xff0c;很多人购买之后反而会觉得眼睛更容易疲劳&#xff0c;有不适的情况&#xff01;最主要的原因是因为挑选的台灯不够专业&#xff0c;次要原因则是使用方法不正确。所以今天跟大家讲…

Android.bp入门指南之浅析Android.bp文件

文章目录 Android.bp文件是什么&#xff1f;Android.bp的主要作用模块定义依赖关系构建规则模块属性插件支持模块的可配置性 为什么会引入Android.bp语法例子 Android.bp文件是什么&#xff1f; Android.bp 文件是 Android 构建系统&#xff08;Android Build System&#xff…

JavaScript基础五对象 内置对象 Math.random()

内置对象-生成任意范围随机数 Math.random() 随机数函数&#xff0c; 返回一个0 - 1之间&#xff0c;并且包括0不包括1的随机小数 [0, 1&#xff09; 如何生成0-10的随机数呢&#xff1f; Math.floor(Math.random() * (10 1)) 放大11倍再向下取整 如何生成5-10的随机数&…

element-ui icon 组件源码分享

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

python爬虫实战——获取酷我音乐数据

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 开发环境: 版 本&#xff1a; python 3.8 编辑器&#xff1a;pycharm 2022.3.2 模块使用: requests >>> pip install requests 如何安装python第三方模块: win R 输入 cmd 点击确定, 输入安装命令 pip install…

k8s kubeadm部署安装详解

目录 kubeadm部署流程简述 环境准备 步骤简述 关闭 防火墙规则、selinux、swap交换 修改主机名 配置节点之间的主机名解析 调整内核参数 所有节点安装docker 安装依赖组件 配置Docker 所有节点安装kubeadm&#xff0c;kubelet和kubectl 定义kubernetes源并指定版本…

【Java】【SSE】【VUE】实现调用千帆大模型,实现打字效果

没有废话。只有演示、和源码地址 效果演示 源码地址 qianfan-sse-demo: 基于https://gitee.com/codinginn/chatgpg-sse-demo-springboot-vue改动

QT SQL

QT SQL模块提供数据库编程的支持&#xff0c;支持多种常见的数据库&#xff1a;MySQL\Oracle\MS SQL Server\SQLite等。SQL模块包含多个类&#xff0c;可以实现&#xff1a;数据库连接、SQL语句执行、数据获取与界面显示 等功能。数据 与 界面间用Model\View架构。 一、 二、Q…

FullStack之Django(2)模型和后台

FullStack之Django(2)模型和后台 author: Once Day date:2022年2月13日/2024年1月31日 漫漫长路&#xff0c;才刚刚开始… 全系列文档请查看专栏: FullStack开发_Once_day的博客-CSDN博客Django开发_Once_day的博客-CSDN博客 参考文档: 编写你的第一个 Django 应用&#…

docker安装定制gocd-agent

一、定制gocd-agent FROM gocd/gocd-agent-alpine-3.12:v21.1.0 MAINTAINER xxx "xxx163.com" # 切换到 root 用户 USER root # 安装 expect、jdk、docker RUN apk update && apk add expect && apk add openjdk8 && apk add docker &&…

Vue3的 组件事件

目录 介绍 触发与监听事件 事件参数 声明触发的事件 事件校验 总结 介绍 Vue3是Vue框架的最新版本&#xff0c;其中对组件事件进行了一些改进和优化。组件事件是Vue中一种常用的通信机制&#xff0c;用于在组件之间传递数据或触发动作。 Vue3中的组件事件主要有两种类型…

Spring Bean 定义常见错误

Spring 的核心是围绕 Bean 进行的。不管是 Spring Boot 还是 Spring Cloud&#xff0c;只要名称中带有 Spring 关键字的技术都脱离不了 Bean&#xff0c;而要使用一个 Bean 少不了要先定义出来&#xff0c;所以定义一个 Bean 就变得格外重要了。 当然&#xff0c;对于这么重要…

2024人工智能可以报考的证书有哪些

人工智能&#xff08;AI&#xff09;是致力于解决通常与人类智能相关联的认知性问题的计算机科学领域&#xff0c;这些问题包括学习、创造和图像识别等。 关键的人工智能技术有哪些&#xff1f; 深度学习神经网络构成了人工智能技术的核心。神经网络反映了人脑中发生的过程。大…

JOSEF约瑟 HRTH-Y-2H2D跳位合位 电源监视继电器 导轨安装

HRTH-Y-2H2D跳位合位 电源监视继电器&#xff1a; HRTH-Y-2H2D-X-T&#xff1b;HRTH-Y-2Z-X-T&#xff1b;HRTH-Y-2H-X-T&#xff1b; HRTH-J-2H2D-X-T&#xff1b;HRTH-J-2Z-X-T;HRTH-J -2H-X-T&#xff1b; HRTH-Y-2H2D&#xff1b;HRTH-Y-2Z&#xff1b;HRTH-Y-2H&#xff1…

遇到ubuntu设置交叉编译环境的问题

今天交叉编译器一直没安装成功&#xff0c;环境变量也配置了还是不对&#xff0c;最后发现Ubuntu是64位的要装 然后就好了 另外在进行嵌入式Linux开发的时候&#xff0c;要把主机、虚拟机、以及开发板设置在同一网段下&#xff0c;虚拟机一般设成临时的就可以&#xff0c;但是…

CS144--Chapter0--wsl2+docker环境搭建

我的笔记本配置 荣耀magicbook16&#xff0c;容量是500G&#xff0c;芯片是R7-5800 由于笔记本容量较小&#xff0c;因此考虑这个方案&#xff0c;对于台式机用户&#xff0c;建议可以直接用虚拟机或者双系统。 前言 斯坦福官网给出的方法是用他们的镜像&#xff08;基于Ubu…

抖音短视频矩阵营销系统源头独立开发搭建

开发背景 抖音短视频矩阵系统源码开发采用模块化设计&#xff0c;包括账号分析、营销活动、数据监控、自动化管理等功能。通过综合分析账号数据&#xff0c;快速发现账号的优势和不足&#xff0c;并提供全面的营销方案&#xff0c;以提高账号曝光率和粉丝数量。同时&#xff0c…