springboot全局异常捕获处理

news2025/4/21 15:15:35

一、需求

实际项目中,经常抛出各种异常,不能直接抛出异常给前端,这样用户体验相当不好,用户看不懂你的Exception,对于一些sql异常,直接抛到页面上也不安全。所以有没有好的办法解决这些问题呢,当然有了,进行全局异常处理,当正常返回给前端就行了。
例如:
在这里插入图片描述

二、引入依赖

 <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
 <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>

 <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>fastjson</artifactId>
           <version>1.2.83</version>
       </dependency>
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.33</version>
       </dependency>

三、创建统一返回结果封装类



import lombok.Data;

@Data
public class Response<T> {

    private int code;
    private String msg;
    private T data;

    public Response() {
    }

    public Response(int code) {
        this.code = code;
    }

    public Response(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Response(T data) {
        this.data = data;
    }

    public Response(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static Response ok() {
        Response response = new Response();
        response.setCode(200);
        response.setMsg("成功");
        return response;
    }

    public static <T> Response<T> ok(T data) {
        Response response = new Response();
        response.setCode(200);
        response.setMsg("成功");
        response.setData(data);
        return response;
    }


    public static Response fail(String msg) {
        Response response = new Response();
        response.setCode(201);
        response.setMsg(msg);
        return response;
    }

    public static Response fail(int code, String msg) {
        Response response = new Response();
        response.setCode(code);
        response.setMsg(msg);
        return response;
    }

}

四、创建状态码常量类

我这里直接用了基本数据类型做状态码,没有写描述,也可以用map的形式创建对象,既有状态码,又有描述。




public class HttpStatusData {

    /**
     * 操作成功
     */
    public static final int SUCCESS = 200;

    /**
     * 对象创建成功
     */
    public static final int CREATED = 201;

    /**
     * 请求已经被接受
     */
    public static final int ACCEPTED = 202;

    /**
     * 操作已经执行成功,但是没有返回数据
     */
    public static final int NO_CONTENT = 204;

    /**
     * 资源已被移除
     */
    public static final int MOVED_PERM = 301;

    /**
     * 重定向
     */
    public static final int SEE_OTHER = 303;

    /**
     * 资源没有被修改
     */
    public static final int NOT_MODIFIED = 304;

    /**
     * 参数列表错误(缺少,格式不匹配)
     */
    public static final int BAD_REQUEST = 400;

    /**
     * 未授权
     */
    public static final int UNAUTHORIZED = 401;

    /**
     * 访问受限,授权过期
     */
    public static final int FORBIDDEN = 403;

    /**
     * 资源,服务未找到
     */
    public static final int NOT_FOUND = 404;

    /**
     * 不允许的http方法
     */
    public static final int BAD_METHOD = 405;

    /**
     * 资源冲突,或者资源被锁
     */
    public static final int CONFLICT = 409;

    /**
     * 不支持的数据,媒体类型
     */
    public static final int UNSUPPORTED_TYPE = 415;

    /**
     * 系统内部错误
     */
    public static final int ERROR = 500;

    /**
     * 接口未实现
     */
    public static final int NOT_IMPLEMENTED = 501;
}

五、编写全局异常类



import com.alibaba.fastjson.JSONException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.ResourceAccessException;

import java.nio.file.AccessDeniedException;
import java.sql.SQLIntegrityConstraintViolationException;

/**
 * @author HTT
 */
@RestControllerAdvice
@Slf4j
public class ExceptionAdviceHandler {

    /**
     * 权限校验异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    public Response handleAccessDeniedException(AccessDeniedException e,
                                                HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址{},权限校验失败{}", requestURI, e.getMessage());
        return Response.fail(HttpStatusData.FORBIDDEN, "没有权限,请联系管理员授权");
    }

    /**
     * 请求方式不支持
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Response handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
                                                        HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址{},不支持{}请求", requestURI, e.getMethod());
        return Response.fail(e.getMessage());
    }

    /**
     * 参数验证失败异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e,
                                                          HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        log.error("请求地址{},参数验证失败{}", requestURI, e.getObjectName(), e);
        return Response.fail(message);
    }

    /**
     * 拦截错误SQL异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public Response handleBadSqlGrammarException(BadSqlGrammarException e,
                                                 HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生数据库异常.", requestURI, e);
        return Response.fail(HttpStatusData.ERROR, "数据库异常!");
    }

    /**
     * 可以拦截表示违反数据库的完整性约束导致的异常。
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(DataIntegrityViolationException.class)
    public Response handleDataIntegrityViolationException(DataIntegrityViolationException e,
                                                          HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生数据库异常.", requestURI, e);
        return Response.fail(HttpStatusData.ERROR, "数据库异常!");
    }


    /**
     * 可以拦截违反数据库的非完整性约束导致的异常,可能也会拦截一些也包括 SQL 语句错误、连接问题、权限问题等各种数据库异常。
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(UncategorizedSQLException.class)
    public Response handleUncategorizedSqlException(UncategorizedSQLException e,
                                                    HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生数据库异常.", requestURI, e);
        return Response.fail(HttpStatusData.ERROR, "数据库异常!");
    }

    /**
     * 拦截未知的运行时异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    public Response handleRuntimeException(RuntimeException e,
                                           HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址{},发生未知运行异常", requestURI, e);
        return Response.fail(e.getMessage());
    }

    /**
     * 业务自定义异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    public Response handleServiceException(BusinessException e,
                                           HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        Integer code = 201;
        log.error("请求地址{},发生业务自定义异常{}", requestURI, e.getMessage(), e);
//        return code != null ? Response.fail(code, e.getMessage()) : Response.fail(e.getMessage());
        return Response.fail(e.getMessage());
    }

    /**
     * 全局异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Response handleException(Exception e,
                                    HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址{},发生系统异常", requestURI, e);
        return Response.fail(e.getMessage());
    }

    /**
     * 发生数据唯一性约束异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public Response sQLIntegrityConstraintViolationException(RuntimeException e,
                                                             HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址{},发生数据唯一性约束异常", requestURI, e);
        return Response.fail(HttpStatusData.ERROR, "数据库异常!,发生数据唯一性约束异常");
    }

    /**
     * 网络请求超时异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(ResourceAccessException.class)
    public Response resourceAccessException(RuntimeException e,
                                            HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址{},网络请求超时异常", requestURI, e);
        return Response.fail(HttpStatusData.ERROR, "网络请求超时异常,调用三方接口异常");
    }

    /**
     * 网络请求超时异常
     *
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(JSONException.class)
    public Response jSONException(RuntimeException e,
                                            HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址{},JSON格式转换异常", requestURI, e);
        return Response.fail(HttpStatusData.ERROR, "JSON格式转换异常");
    }

}

六、创建自定义异常类



/**
 * @author: wr
 * @date: 2020/2/17 18:03
 */
public class BusinessException extends RuntimeException {
    /**
     * 无参构造函数
     */
    public BusinessException(){
        super();
    }

    /**
     * 指定异常信息构造函数
     * @param message
     */
    public BusinessException(String message){
        super(message);
    }
}


七、 编写测试类


@RestController
@RequestMapping
public interface EntrepreneurPortraitApi {

    @PostMapping("/test")
    public void test(){
        throw new BusinessException("测试全局异常是否生效");
    }
    

 }   

八、测试结果

启动项目,浏览器访问 http://localhost:8888/test

{
  "code": 201,
  "msg": "失败",
  "data": "测试全局异常是否生效"
}

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

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

相关文章

【文献阅读】EndoNet A Deep Architecture for Recognition Tasks on Laparoscopic Videos

关于数据集的整理 Cholec80 胆囊切除手术视频数据集介绍 https://zhuanlan.zhihu.com/p/700024359 数据集信息 Cholec80 数据集 是一个针对内窥镜引导 下的胆囊切除手术视频流程识别数据集。数据集提供了每段视频中总共7种手术动作及总共7种手术工具的标注&#xff0c;标…

基于springboot的个人财务管理系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

Linux系统编程---孤儿进程与僵尸进程

1、前言 在上一篇博客文章已经对Linux系统编程内容进行了较为详细的梳理&#xff0c;本文将在上一篇的基础上&#xff0c;继续梳理Linux系统编程中关于孤儿进程和僵尸进程的知识脉络。如有疑问的博客朋友可以通过下面的博文链接进行参考学习。 Linux系统编程---多进程-CSDN博客…

简单使用MCP

简单使用MCP 1 简介 模型上下文协议&#xff08;Model Context Protocol&#xff0c;MCP&#xff09;是由Anthropic&#xff08;产品是Claude&#xff09;推出的开放协议&#xff0c;它规范了应用程序如何向LLM提供上下文。MCP可帮助你在LLM之上构建代理和复杂的工作流。 从…

MySQL:9.表的内连和外连

9.表的内连和外连 表的连接分为内连和外连 9.1 内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选&#xff0c;之前查询都是内连 接&#xff0c;也是在开发过程中使用的最多的连接查询。 语法&#xff1a; select 字段 from 表1 inner join 表2 on 连接…

在阿里云和树莓派上编写一个守护进程程序

目录 一、阿里云邮件守护进程 1. 安装必要库 2. 创建邮件发送脚本 mail_daemon.py 3. 设置后台运行 二、树莓派串口守护进程 1. 启用树莓派串口 2. 安装依赖库 3. 创建串口输出脚本 serial_daemon.py 4. 设置开机自启 5. 使用串口助手接收 一、阿里云邮件守护进程 1.…

基于前端技术的QR码API开发实战:从原理到部署

前言 QR码&#xff08;Quick Response Code&#xff09;是一种二维码&#xff0c;于1994年开发。它能快速存储和识别数据&#xff0c;包含黑白方块图案&#xff0c;常用于扫描获取信息。QR码具有高容错性和快速读取的优点&#xff0c;广泛应用于广告、支付、物流等领域。通过扫…

RenderStage::drawInner

文章目录 RenderStage::drawInnerOSG渲染后台关系图OSG的渲染流程RenderBin::draw(renderInfo,previous)RenderBin::drawImplementationRenderLeaf::renderosg::State::apply(const StateSet*)Drawable::draw(RenderInfo& renderInfo)Drawable::drawInner(RenderInfo& …

C++初阶-类和对象(中)

目录 1.类的默认成员函数 2.构造函数&#xff08;难度较高&#xff09; ​编辑 ​编辑 ​编辑 3.析构函数 4.拷贝构造函数 5.赋值运算符重载 5.1运算符重载 5.2赋值运算符重载 6.取地址运算符重载 6.1const成员函数 6.2取地址运算符重载 7.总结 1.类的默认成员函数…

智谱开源新一代GLM模型,全面布局AI智能体生态

2024年4月15日&#xff0c;智谱在中关村论坛上正式发布了全球首个集深度研究与实际操作能力于一体的AI智能体——AutoGLM沉思。这一革命性技术的发布标志着智谱在AGI&#xff08;通用人工智能&#xff09;领域的又一次重要突破。智谱的最新模型不仅推动了AI智能体技术的升级&am…

分治-快排-75.颜色分类-力扣(LeetCode)

一、题目解析 给定一个数组将其元素按照0&#xff0c;1,&#xff0c;2三段式排序&#xff0c;并且在原地进行排序。 二、算法原理 解法&#xff1a;三指针 用cur遍历数组&#xff0c;left记录0的最左侧&#xff0c;right记录2的最右侧。 left初始值为-1&#xff0c;right的初…

铅酸电池充电器方案EG1253+EG4321

参考&#xff1a; 基于EG1253EG4321铅酸电池(48V20AH)三段式充电器 屹晶微高性价比的电瓶车充电器方案——EG1253 电瓶电压 48V电瓶锂电池&#xff0c;其充满约为55V~56V&#xff0c;因此充电器输出电压为55V~56V&#xff1b; 若是48V铅酸电池&#xff0c;标称电压为48V&…

vue 中formatter

:formatter 是前端表格组件&#xff08;如 Element UI、Vxe-Table 等&#xff09;中用于 ​​自定义单元格内容显示格式​​ 的属性。它的核心作用是&#xff1a;将后端返回的原始数据&#xff08;如编码、状态值等&#xff09;转换为更友好、更易读的文本。 这段代码 :forma…

协程?协程与线程的区别?Java是否支持协程?

一、前言 协程&#xff08;Coroutine&#xff09; 是一种轻量级的并发编程模型&#xff0c;允许在单线程内通过协作式多任务调度实现并发。由用户代码显式控制&#xff08;用户态调度而非操作系统内核调度&#xff09;&#xff0c;避免了线程上下文切换的开销&#xff0c;适合…

Muduo网络库实现 [十六] - HttpServer模块

目录 设计思路 类的设计 模块的实现 公有接口 私有接口 疑问点 设计思路 本模块就是设计一个HttpServer模块&#xff0c;提供便携的搭建http协议的服务器的方法。那么这个模块需要如何设计呢&#xff1f; 这还需要从Http请求说起。 首先从http请求的请求行开始分析&…

关于进程状态

目录 进程的各种状态 运行状态 阻塞状态 挂起状态 linux中的进程状态、 进程状态查看 S状态&#xff08;浅睡眠&#xff09; t 状态&#xff08;追踪状态&#xff09; T状态&#xff08;暂停状态&#xff09; ​编辑 kill命令手册 D状态&#xff08;深度睡眠&#…

SQL注入 01

0x01 用户、脚本、数据库之间的关系 首先客户端发出了ID36的请求&#xff0c;脚本引擎收到后将ID36的请求先代入脚本的sql查询语句Select * from A where id 36 &#xff0c; 然后将此代入到数据库中进行查询&#xff0c;查到后将返回查询到的所有记录给脚本引擎&#xff0c;接…

学习笔记:黑马程序员JavaWeb开发教程(2025.3.24)

11.2 案例-文件上传-简介 火狐浏览器可以看到文件上传传递的底层数据&#xff0c;而chrome对这一块数据进行了包装 在输出日志代码处打了一个断点&#xff0c;看服务端接收到的数据&#xff0c;在上传文件的保存地址中&#xff0c;可以看到&#xff0c;有三个临时文件&…

计算机视觉cv2入门之视频处理

在我们进行计算机视觉任务时&#xff0c;经常会对视频中的图像进行操作&#xff0c;这里我来给大家分享一下&#xff0c;cv2对视频文件的操作方法。这里我们主要介绍cv2.VideoCapture函数的基本使用方法。 cv2.VideoCapture函数 当我们在使用cv2.VideoCapture函数时&#xff…

【Linux】Rhcsa复习5

一、Linux文件系统权限 1、文件的一般权限 文件权限针对三类对象进行定义&#xff1a; owner 属主&#xff0c;缩写u group 属组&#xff0c; 缩写g other 其他&#xff0c;缩写o 每个文件针对每类访问者定义了三种主要权限&#xff1a; r&#xff1a;read 读 w&…