SpringBoot如何进行全局异常处理?

news2024/11/16 2:28:29

1.为什么需要全局异常处理?

在日常开发中,为了不抛出异常堆栈信息给前端页面,每次编写Controller层代码都要尽可能的catch住所有service层、dao层等异常,代码耦合性较高,且不美观,不利于后期维护。

应用场景是什么?

  • 非常方便的去掉了try...catch这类冗杂难看的代码,有利于代码的整洁和优雅
  • 自定义参数校验时候全局异常处理会捕获异常,将该异常统一返回给前端,省略很多if...else代码
  • 当后端出现异常时,需要返回给前端一个友好的界面的时候就需要全局异常处理
  • 因为异常时层层向上抛出的,为了避免控制台打印一长串异常信息

2.代码工程

实验目的

实现全局异常拦截

controller

package com.et.exception.controller;

import com.et.exception.config.BizException;
import com.et.exception.model.User;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
public class HelloWorldController {
    @RequestMapping("/hello")
    public Map<String, Object> showHelloWorld(){
        Map<String, Object> map = new HashMap<>();
        map.put("msg", "HelloWorld");
        return map;
    }
   @PostMapping("/user")
   public boolean insert(@RequestBody User user) {
      System.out.println("add...");
      if(user.getName()==null){
         throw  new BizException("-1","username is empty!");
      }
      return true;
   }

   @PutMapping("/user")
   public boolean update(@RequestBody User user) {
      System.out.println("update...");
      //mock NullException
      String str=null;
      str.equals("111");
      return true;
   }

   @DeleteMapping("/user")
   public boolean delete(@RequestBody User user)  {
      System.out.println("delete...");
      //mock Exception
      Integer.parseInt("abc123");
      return true;
   }


}

globe exception config

定义全局异常拦截类

package com.et.exception.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class GlobalExceptionHandler {
   private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
   
   /**
    *process BizException
    * @param req
    * @param e
    * @return
    */
    @ExceptionHandler(value = BizException.class)
    @ResponseBody
   public  ResultBody bizExceptionHandler(HttpServletRequest req, BizException e){
       logger.error("biz exception!the reason is:{}",e.getErrorMsg());
       return ResultBody.error(e.getErrorCode(),e.getErrorMsg());
    }

   /**
    * process NUllException
    * @param req
    * @param e
    * @return
    */
   @ExceptionHandler(value =NullPointerException.class)
   @ResponseBody
   public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e){
      logger.error("null exception!the reason is:",e);
      return ResultBody.error(CommonEnum.BODY_NOT_MATCH);
   }


    /**
    * unkown Exception
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value =Exception.class)
   @ResponseBody
   public ResultBody exceptionHandler(HttpServletRequest req, Exception e){
       logger.error("unkown Exception!the reason is:",e);
           return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
    }
}

自定义业务异常

package com.et.exception.config;

public class BizException extends RuntimeException {

   private static final long serialVersionUID = 1L;


   protected String errorCode;

   protected String errorMsg;

   public BizException() {
      super();
   }

   public BizException(BaseErrorInfoInterface errorInfoInterface) {
      super(errorInfoInterface.getResultCode());
      this.errorCode = errorInfoInterface.getResultCode();
      this.errorMsg = errorInfoInterface.getResultMsg();
   }
   
   public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {
      super(errorInfoInterface.getResultCode(), cause);
      this.errorCode = errorInfoInterface.getResultCode();
      this.errorMsg = errorInfoInterface.getResultMsg();
   }
   
   public BizException(String errorMsg) {
      super(errorMsg);
      this.errorMsg = errorMsg;
   }
   
   public BizException(String errorCode, String errorMsg) {
      super(errorCode);
      this.errorCode = errorCode;
      this.errorMsg = errorMsg;
   }

   public BizException(String errorCode, String errorMsg, Throwable cause) {
      super(errorCode, cause);
      this.errorCode = errorCode;
      this.errorMsg = errorMsg;
   }
   

   public String getErrorCode() {
      return errorCode;
   }

   public void setErrorCode(String errorCode) {
      this.errorCode = errorCode;
   }

   public String getErrorMsg() {
      return errorMsg;
   }

   public void setErrorMsg(String errorMsg) {
      this.errorMsg = errorMsg;
   }

   public String getMessage() {
      return errorMsg;
   }

   @Override
   public Throwable fillInStackTrace() {
      return this;
   }

}

自定义返回结果

package com.et.exception.config;

import com.alibaba.fastjson.JSONObject;

public class ResultBody {

   private String code;

   private String message;


   private Object result;

   public ResultBody() {
   }

   public ResultBody(BaseErrorInfoInterface errorInfo) {
      this.code = errorInfo.getResultCode();
      this.message = errorInfo.getResultMsg();
   }

   public String getCode() {
      return code;
   }

   public void setCode(String code) {
      this.code = code;
   }

   public String getMessage() {
      return message;
   }

   public void setMessage(String message) {
      this.message = message;
   }

   public Object getResult() {
      return result;
   }

   public void setResult(Object result) {
      this.result = result;
   }


   public static ResultBody success() {
      return success(null);
   }

   public static ResultBody success(Object data) {
      ResultBody rb = new ResultBody();
      rb.setCode(CommonEnum.SUCCESS.getResultCode());
      rb.setMessage(CommonEnum.SUCCESS.getResultMsg());
      rb.setResult(data);
      return rb;
   }


   public static ResultBody error(BaseErrorInfoInterface errorInfo) {
      ResultBody rb = new ResultBody();
      rb.setCode(errorInfo.getResultCode());
      rb.setMessage(errorInfo.getResultMsg());
      rb.setResult(null);
      return rb;
   }


   public static ResultBody error(String code, String message) {
      ResultBody rb = new ResultBody();
      rb.setCode(code);
      rb.setMessage(message);
      rb.setResult(null);
      return rb;
   }


   public static ResultBody error( String message) {
      ResultBody rb = new ResultBody();
      rb.setCode("-1");
      rb.setMessage(message);
      rb.setResult(null);
      return rb;
   }

   @Override
   public String toString() {
      return JSONObject.toJSONString(this);
   }

}

实体类

package com.et.exception.model;

import com.alibaba.fastjson.JSONObject;

import java.io.Serializable;

public class User implements Serializable {
   private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private int age;
    
    public User(){
    }

   public int getId() {
      return id;
   }
   
   public void setId(int id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   public String toString() {
      return JSONObject.toJSONString(this);
   }
}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • GitHub - Harries/springboot-demo: a simple springboot demo with some components for example: redis,solr,rockmq and so on.(exception)

3.测试

启动Spring Boot项目

模拟业务异常

1

模拟null异常

​编辑0%模拟其他异常

3

4.引用

  • SpringBoot如何进行全局异常处理? | Harries Blog™

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

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

相关文章

基于java的少儿编程网上报名系统+vue

TOC ssm006基于java的少儿编程网上报名系统vue 研究背景 近年来&#xff0c;随着网络技术的不断发展&#xff0c;越来越多人在网站查询各种信息&#xff0c;少儿编程网上报名系统对用户和管理员都有很大帮助&#xff0c;少儿编程网上报名系统通过和数据库管理系软件协作来实…

基于STM32开发的智能安防报警系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 系统初始化传感器数据采集与处理报警控制与通知Wi-Fi通信与远程监控应用场景 家庭安防管理商铺和办公室的智能安防常见问题及解决方案 常见问题解决方案结论 1. 引言 随着智能家居和物联网技…

拟合的置信区间

目标图: 图片来源:Fig. 4e from Arwani, Ruth Theresia, et al. "Stretchable ionic–electronic bilayer hydrogel electronics enable in situ detection of solid-state epidermal biomarkers." Nature Materials (2024): 1-8. 1. 数据输入 假设原始数据如下:…

书生大模型实战营第三期基础岛第二课——8G 显存玩转书生大模型 Demo

8G 显存玩转书生大模型 Demo 基础任务进阶作业一&#xff1a;进阶作业二&#xff1a; 基础任务 使用 Cli Demo 完成 InternLM2-Chat-1.8B 模型的部署&#xff0c;并生成 300 字小故事&#xff0c;记录复现过程并截图。 创建conda环境 # 创建环境 conda create -n demo pytho…

协作新选择:即时白板在线白板软件分享

在团队合作中&#xff0c;产品经理扮演着至关重要的角色&#xff0c;他们不仅是产品与用户之间的纽带&#xff0c;更是产品性能和用户需求的桥梁。他们需要深入参与产品的研发过程&#xff0c;并与研发团队保持紧密的沟通。因此&#xff0c;产品经理需要一款高效的协作工具来提…

纯电SUV挑花眼了?看看这两款十多万的家用SUV谁更香

文/王俣祺 导语&#xff1a;随着新能源技术的日益成熟&#xff0c;现如今纯电汽车已经在市场上卖得风生水起。早些时候人们可能还会对纯电汽车抱有“续航焦虑”&#xff0c;但随着各个车型在电池容量以及能耗方面都迎来了进步&#xff0c;充电网络也日渐完善&#xff0c;选择一…

多商户多套部署需修改注意事项

同一台服务器上部署多个多商户项目&#xff0c;需要修改和调整的地方等。 一、修改代码中的端口号&#xff0c;需要两个项目不能使用同一个端口号&#xff0c;例如&#xff1a;A项目用&#xff1a;8324&#xff0c;B项目用&#xff1a;8325&#xff1b; 二、修改反向代理&…

认识泛型VS包装类

1.包装类 在 Java 中&#xff0c;由于基本类型不是继承自 Object &#xff0c;为了在泛型代码中可以支持基本类型&#xff0c; Java 给每个基本类型都对应了 一个包装类型。 ps:为什么需要包装类&#xff1f;说白了java就是面向对象编程的 比如&#xff1a;Java 的集合框架&am…

笔记整理—uboot启动过程(3)栈的二次设置以及常用名词解析,BL1部分完

前文说到了uboot的lowlevel_init都干了些什么&#xff0c;也就是经过了这项初期的低级启动&#xff0c;使得我们能在串口监视器上看见机器打印出的第一句话“OK”。当lowlevel_init结束后&#xff0c;uboot去做了另一件事情&#xff0c;那就是栈的再次设置。 第一次栈设置发生在…

昂科烧录器支持Analogix硅谷数模的USB-C端口控制器ANX7406

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中Analogix硅谷数模的USB-C端口控制器ANX7406已经被昂科的通用烧录平台AP8000所支持。 ANX7406是一款USB Type-C™&#xff08;USB-C&#xff09;端口控制器&#xff0c;符合最新…

网络 通信

一、客户端接收(也可以bind) 1. socket socket 函数 用于创建一个套接字&#xff08;socket&#xff09;&#xff0c;这是网络通信的基础。 它的原型如下&#xff1a;int socket(int domain, int type, int protocol); 参数&#xff1a; domain&#xff1a;指定协议族&…

go-zero接入skywalking链路追踪

文章目录 Skywalking本地测试搭建项目引入dockerfile打包引入最后效果图 Skywalking本地测试搭建 这里用Docker搭建 #数据存储用ES&#xff0c;搭建ES docker run -d -p 9200:9200 -p 9300:9300 --name es -e "discovery.typesingle-node" -e ES_JAVA_OPTS"-X…

【C++】12.智能指针

在上一篇博客【C】11.异常中我们知道有些时候会造成内存空间的未释放从而导致内存泄漏&#xff0c;因此本篇博客的内容就是如何减少内存泄漏——智能指针。 一、RAII RAII&#xff08;Resource Acquisition Is Initialization&#xff09;是一种利用对象生命周期来控制程序资…

基于单片机的指纹识别考勤系统设计

本设计基于STC89C52为主控的指纹考勤系统&#xff0c;主要分为光学AS608指纹识别模块、LCD12864液晶模块、AT24C02存储芯片、DS1302时钟芯片模块、矩阵按键模块。AS608指纹模块进行指纹的采集&#xff1b;矩阵按键能实现对指纹的录入、删除、编号&#xff1b;AT24C02存储模块对…

如何使用ssm实现网上服装销售系统

TOC ssm047网上服装销售系统jsp 第一章 绪 论 1.1背景及意义 系统管理也都将通过计算机进行整体智能化操作&#xff0c;对于网上服装销售系统系统所牵扯的管理及数据保存都是非常多的&#xff0c;例如管理员&#xff1b;主页、个人中心、用户管理、商品分类管理、商品信息管…

[Meachines] [Easy] Optimum HFS文件管理2.3.x-RCE+MS16-032

信息收集 IP AddressOpening Ports10.10.10.8TCP:80 $ nmap -p- 10.10.10.8 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 80/tcp open http HttpFileServer httpd 2.3 |_http-server-header: HFS 2.3 |_http-title: HFS / Service Info: OS: Windows; CP…

Python计算机视觉 第2章-局部图像描述子

Python计算机视觉 第2章-局部图像描述子 2.1 Harris角点检测器 Harris角点检测算法&#xff08;也称Harris & Stephens角点检测器&#xff09;是一个极为简单的角点检测算法。该算法的主要思想是&#xff0c;如果像素周围显示存在多于一个方向的边&#xff0c;我们认为该…

滥用 DHCP 管理员组来提升 Windows 域中的权限

介绍 从 Google Docs 到 Active Directory,访问管理几乎影响到组织中的每个角色。在讨论权限和访问控制时,如何最大限度地减少员工的挫败感而不增加不必要的风险是一个微妙的平衡——安全团队痛苦地意识到了这一点。 因此,“刚好足够的访问权限”是任何访问策略的关键要素…

鸿蒙内核源码分析(用户态锁篇) | 如何使用快锁Futex(上)

快锁上下篇 鸿蒙内核实现了Futex&#xff0c;系列篇将用两篇来介绍快锁&#xff0c;主要两个原因: 网上介绍Futex的文章很少&#xff0c;全面深入内核介绍的就更少&#xff0c;所以来一次详细整理和挖透。涉及用户态和内核态打配合&#xff0c;共同作用&#xff0c;既要说用户…

日志文件切割:以分隔割tomcat 的 catalina.out 文件为例子

文章目录 引言I 日志文件切割使用用crontab工具,定时执行任务通过Linux系统自带的切割工具logrotate来进行切割【推荐】基于其他日志框架进行分隔II 扩展logrotate 简介logrotate 用法引言 问题:tomcat 的 catalina.out 文件不会进行日志切割,当这个文件大于2G 时,会影响to…