【Spring Boot统一功能处理】统一异常处理,统一的返回格式,@ControllerAdvice简单分析,即将走进SSM项目的大门! ! !

news2025/1/12 19:47:05

前言:
大家好,我是良辰丫,在上一篇文章中我们已经学习了一些统一功能处理的相关知识,今天我们继续深入学习这些知识,主要学习统一异常处理,统一的返回格式,@ControllerAdvice简单分析.💌💌💌

🧑个人主页:良辰针不戳
📖所属专栏:javaEE进阶篇之框架学习
🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。
💦期待大家三连,关注,点赞,收藏。
💌作者能力有限,可能也会出错,欢迎大家指正。
💞愿与君为伴,共探Java汪洋大海。

在这里插入图片描述

目录

  • 1. 统一异常处理
    • 1.1 制造一个算术异常
    • 1.2 处理异常
  • 2. 统一的返回格式
    • 2.1 为什么需要统一返回格式呢?
    • 2.2 写一个随机返回数函数
    • 2.3 创建一个类并且添加@ControllerAdvice
    • 2.4 实现ResponseBodyAdvice接口并重写方法
    • 2.5 返回格式处理String类型出现问题
  • 3. @ControllerAdvice简单分析

1. 统一异常处理

1.1 制造一个算术异常

我们首先来制造一个算术异常,除数不能为0.

   @RequestMapping("/login")
    public String login(){
        int num = 10/0;
        return "执行了login";
    }

我们先不用处理异常,观察我们的浏览器效果.

在这里插入图片描述

1.2 处理异常

  • 创建一个类,在类上标识注解@ControllerAdvice,这个注解可以感知异常.
  • 通过注解 @ExceptionHandler来订阅异常

package com.example.demo;


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;

@ResponseBody
@ControllerAdvice
public class ExDeal {
    @ExceptionHandler(ArithmeticException.class)
    public HashMap<String, String> arithmeticException(ArithmeticException e) {
        HashMap<String, String> result = new HashMap<>();
        result.put("code", "-1");
        result.put("msg", "算术异常异常:" + e.getMessage()); // 错误码的描述信息
        result.put("data", "除数不能为0");
        return result;
    }
}

Exception包含所有的异常,参数写成Exception也可以,注意是方法的参数.

接下来我们观察浏览器效果.

在这里插入图片描述

2. 统一的返回格式

注意 : 我们在上一篇文章学习了拦截器,我们制定了一些拦截规则,我们一会要举一个例子进行测试我们的统一的返回格式,因此我们可以先把拦截器的代码注释掉.

2.1 为什么需要统一返回格式呢?

  • ⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。
  • 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就⾏了,因为所有接⼝都是这样返回的。
  • 有利于项⽬统⼀数据的维护和修改。
  • 有利于后端技术部⻔的统⼀规范的标准制定,不会出现稀奇古怪的返回内容。
  • 也就是前后端做出格式约定,可以极大的方便程序员去处理各种各样的问题,格式不统一会有格式转换等不便捷的缺点,也不利于程序员维护.

2.2 写一个随机返回数函数

我们先在user类中写一个随机返回数字代码,运行通过浏览器观察效果.

@RequestMapping("/num")
public Integer num(){
    Random random = new Random();
    int num = random.nextInt(1000);
    return num;
}

在这里插入图片描述
然而后端并不知道我们的格式,因为我们可能是字符串,整型等各种各样的数据类型.

2.3 创建一个类并且添加@ControllerAdvice

package com.example.demo;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice
public class Respons {

   }

2.4 实现ResponseBodyAdvice接口并重写方法

我们要实现ResponseBodyAdvice接口,并且重写supports方法以及beforeBodyWrite方法(统一对象急速在此方法中实现的)

package com.example.demo;

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
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.RequestBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;

@ControllerAdvice
public class Response implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        //默认是false,表示开关关掉,意味着下面的重写效果没有用途
//        return false;
        //返回true的时候才会执行下面的beforeBodyWrite方法
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        HashMap<String,Object> map = new HashMap<>();
        //添加状态码,200表示成功
        map.put("code","200");
        //错误的描述信息
        map.put("msg",null);
        //数据body
        map.put("data",body);
        return map;
    }
}

然后我们观察统一格式后的效果

在这里插入图片描述

2.5 返回格式处理String类型出现问题

我们在login中返回的是一个字符串,当我们通过浏览器访问我们的login页面的时候会发现有一定的问题,错误是不能进行类型转化,这是为什么呢?

在这里插入图片描述

  • String既不属于基本数据类型,又不属于对象.
  • String使用的是自己的格式化工具,我们需要使用jackon进行类型转换.
  • 因此如果是String需要特殊处理,我们先要通过属性注入把ObjectMapper注入进来,因为处理String需要这个方法.
package com.example.demo;

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.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
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.RequestBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;

@ControllerAdvice
public class Response implements ResponseBodyAdvice {

    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        //默认是false,表示开关关掉,意味着下面的重写效果没有用途
//        return false;
        //返回true的时候才会执行下面的beforeBodyWrite方法
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        HashMap<String,Object> map = new HashMap<>();
        //添加状态码,200表示成功
        map.put("code","200");
        //错误的描述信息
        map.put("msg",null);
        //数据body
        map.put("data",body);

        if (body instanceof String) {
            // 需要特殊处理,因为 String 在转换的时候会报错
            try {
                return objectMapper.writeValueAsString(map);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return map;
    }
}

接下来我们再次观察我们的浏览器页面效果.

在这里插入图片描述

3. @ControllerAdvice简单分析

  1. 我们先进入 @ControllerAdvice源码中,我们惊奇的发现@ControllerAdvice也是来自于组件@Component.⽽所有组件初始化都会调⽤InitializingBean 接⼝。

在这里插入图片描述

  1. 接下来我们来看 InitializingBean 有哪些实现类?在资料中我们发现 Spring MVC中的实现⼦类是 RequestMappingHandlerAdapter,我们找到一个initControllerAdviceCache方法.

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 我们发现这个⽅法在执⾏是会查找使⽤所有的 @ControllerAdvice 类,发⽣某个事件时,调⽤相应的 Advice ⽅法,⽐如返回数据前调⽤统⼀数据封装,⽐如发⽣异常是调⽤异常的Advice ⽅法实现。
  • 换句话来说,就是有各种各样的Advice来处理不同的事件,如果出现了异常事件就会通过@ControllerAdvice注解调用异常事件相关的Advice进行检测异常(就是定位异常),然后通过我们的后端代码处理异常.

后序:
在Spring Boot统一功能处理我们主要学习了统一用户登录权限验证,统一数据格式返回,统一异常处理,这些都是在我们的SSM项目中非常重要的,我们需要重点去掌握.🚀🚀🚀

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

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

相关文章

邀请功能的实现分析

邀请功能 功能分析 场景&#xff1a;项目中出现用户邀请其他用户加入群组的功能 需求&#xff1a;用户点击生成邀请链接可以生成一个url&#xff0c;将这个url分享给其他用户&#xff0c;其他用户点击后对用户登录状态进行校验&#xff0c;校验通过即可加入群组&#xff0c;…

【dubbo triple provider 底层流转】

一、maven依赖 <dependency><groupId>io.netty</groupId><artifactId>netty-codec-http2</artifactId><version>4.1.90.Final</version> </dependency><dependency><groupId>org.apache.dubbo</groupId>&l…

vue3 父子组件传值 记录

最近这个组件之间传值用的较多&#xff0c;我这该死的记性&#xff0c;总给忘记写法&#xff0c;特此记录下 第一种 父传子 补充&#xff1a;LeftView.vue 是父组件&#xff1b; Video.vue 是子组件 第二种 子传父 Video.vue 子组件 第一步 引入&#xff1a; import { de…

Linux搭建Discuz论坛

环境&#xff1a;redhat 9 mysql 8 Discuz 3.5 题目要求&#xff1a;在 bbs.example.com 主机上创建 Discuz 论坛&#xff0c;数据库服务器使用 db.example.com 主机的 bbs 数据库实例&#xff0c;该实例由 MySQL数据库软件提供服务。 题目要求没有说是在一台虚拟机…

PostgreSQL学习笔记

目录 一、PostgreSQL安装 1、下载 2、安装 二、PostgreSQL操作 1、数据库操作 2、表操作 3、数据操作 一、PostgreSQL安装 本章节以windows系统安装为例&#xff0c;讲解PostgreSQL 15.0的安装过程。 1、下载 访问PostgreSQL官方网站&#xff0c;下载对应的安装包&am…

Qt/C++编写超精美自定义控件(历时9年更新迭代/超202个控件/祖传原创)

一、前言 无论是哪一门开发框架&#xff0c;如果涉及到UI这块&#xff0c;肯定需要用到自定义控件&#xff0c;越复杂功能越多的项目&#xff0c;自定义控件的数量就越多&#xff0c;最开始的时候可能每个自定义控件都针对特定的应用场景&#xff0c;甚至里面带了特定的场景的…

多元回归预测 | Matlab基于麻雀算法(SSA)优化混合核极限学习机HKELM回归预测, SSA-HKELM数据回归预测,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab基于麻雀算法(SSA)优化混合核极限学习机HKELM回归预测, SSA-HKELM数据回归预测,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 …

Idea中使用Git详细教学

目录 一、配置 Git 二、创建项目远程仓库 三、初始化本地仓库 方法一&#xff1a; 方法二&#xff1a; 四、连接远程仓库 五、提交与拉取到本地仓库 六、推送到远程仓库 七、克隆远程仓库到本地 方法一&#xff1a; 方法二&#xff1a; 八、Git分支操作 一、配置 G…

GAMES101笔记 Lecture07 Shading1(Illumination, Shading and Graphics Pipeline)

目录 Visibility / Occlusion(可见性 or 遮挡)Painters Algorithm(画家算法)Z-Buffer(深度缓冲算法) Shading(着色)A Simple Shading Model(Blinn-Phong Reflectance Model)一个简单的着色模型&#xff1a;Blinn-Phong反射模型Diffuse Reflection(漫反射) 参考资源 Visibility …

Learn Mongodb了解DB数据库 ①

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; PHP MYSQL &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…

flash attention论文及源码学习

​ 论文 attention计算公式如下 传统实现需要将S和P都存到HBM&#xff0c;需要占用 O ( N 2 ) O(N^{2}) O(N2)内存&#xff0c;计算流程为 因此前向HBM访存为 O ( N d N 2 ) O(Nd N^2) O(NdN2)&#xff0c;通常N远大于d&#xff0c;GPT2中N1024&#xff0c;d64。HBM带宽…

#10043. 「一本通 2.2 例 1」剪花布条(内附封面)

题目描述 原题来自&#xff1a;HDU 2087 一块花布条&#xff0c;里面有些图案&#xff0c;另有一块直接可用的小饰条&#xff0c;里面也有一些图案。对于给定的花布条和小饰条&#xff0c;计算一下能从花布条中尽可能剪出几块小饰条来呢&#xff1f; 输入格式 输入数据为多…

23年6月1日软著又面临改革,个人加分评职称和企业申报项目加分的软件著作权登记证书该如何申请?

23年6月1号&#xff0c;国家版权局对软件著作权的申请又做出了改革&#xff0c;本次改革的主要内容是全面普及线上办公。申请人无需向中心递交或邮寄登记申请纸介质材料&#xff0c;“足不出户”即可完成版权登记。 软件著作权登记实现无纸化后&#xff0c;申请人在线登记办理…

1.2g可视化大屏项目分享【包含数字孪生、视频监控、智慧城市、智慧交通等】

1.2g可视化大屏项目分享【包含数字孪生、视频监控、智慧城市、智慧交通等】 链接&#xff1a;https://pan.baidu.com/s/1KSNll7b6bVoVPPqcQmNKeQ 提取码&#xff1a;w13x

Android 图形系统-图解和初步探究

Android 图形系统-图解和初步探究_猎羽的博客-CSDN博客https://blog.csdn.net/feather_wch/article/details/131486729 Android图形系统 2023-7-1 问题&#xff1a;如何将一帧画面显示到屏幕上&#xff1f; 绘制流程 Activity代码 Window的结构 绘制流程 Activity启动后&a…

JDK 动态代理为什么只能代理有接口的类?

嗯&#xff0c;这个问题的核心本质&#xff0c;是 JDK 动态代理本身的机制来决定的。 首先&#xff0c;在 Java 里面&#xff0c;动态代理是通过 Proxy.newProxyInstance()方法来实现的&#xff0c;它需 要传入被动态代理的接口类。 之所以要传入接口&#xff0c;不能传入类&a…

MYSQL增删改语句

INSERT 语法: 单行插入 INSERT INTO table_name (column_1, column_2, ...) VALUES (value_1, value_2, ...); 多行插入 INSERT INTO table_name (column_1, column_2, ...) VALUES (value_11, value_12, ...),(value_21, value_22, ...)...; INSERT INTO 和 VALUES都是关键词 …

libGL.so.1: cannot open shared object file: No such file or directory

不适用docker环境&#xff0c;在conda虚拟环境中出现如下错误&#xff1a; 解决办法&#xff1a; 参考资料 【解决方法】libGL.so.1: cannot open shared object file: No such file or directory

高性能分布式缓存Redis(三) 扩展应用

一、分布式锁 在并发编程中&#xff0c;通过锁&#xff0c;来避免由于竞争而造成的数据不一致问题 1.1、高并发下单超卖问题 Autowired RedisTemplate<String, String> redisTemplate;String key "maotai20210319001";//茅台商品编号ScheduledExecutorServ…

【线程池】史上最全的ScheduledThreadPoolExecutor源码分析

目录 一、简介 1.1 继承关系 1.2 使用 1.3 例子 二、源码分析 2.1 构造方法 2.2 主要的四种提交执行任务的方法 2.3 内部类 ScheduledFutureTask 2.3 scheduleAtFixedRate()方法 2.4 delayedExecute()方法 2.5 ScheduledFutureTask类的run()方法 2.6 内部类 Delaye…