Spring异常处理-@ExceptionHandler-@ControllerAdvice-全局异常处理

news2024/11/17 0:38:01

文章目录

  • @ResponseBody
  • @ControllerAdvice
  • 最终的异常处理方式

异常的处理分两类
编程式处理:也就是我们的try-catch
声明式处理:使用注解处理
在这里插入图片描述

@ResponseBody


/**
 * 测试声明式异常处理
 */
@RestController
public class HelloController {


    //编程式的异常处理;
    //如果大量业务都需要加异常处理代码的话,会很麻烦
//        try {
//            //执行业务
//
//        }catch (Exception e){
//            return R.error(100,"执行异常");
//        }
    @GetMapping("/hello")
    public R hello(@RequestParam(value = "i",defaultValue = "0") Integer i) throws FileNotFoundException {
        int j = 10 / i;

//        FileInputStream inputStream = new FileInputStream("D:\\123.txt");
        String s = null;
        s.length();
        return R.ok(j);
    }


    /**
     * 1、如果Controller本类出现异常,会自动在本类中找有没有@ExceptionHandler标注的方法,
     *    如果有,执行这个方法,它的返回值,就是客户端收到的结果
     *  如果发生异常,多个都能处理,就精确优先
     * @return
     */
    @ResponseBody
    @ExceptionHandler(ArithmeticException.class)
    public R handleArithmeticException(ArithmeticException ex){
        System.out.println("【本类】 - ArithmeticException 异常处理");
        return R.error(100,"执行异常:" + ex.getMessage());
    }


    @ExceptionHandler(FileNotFoundException.class)
    public R handleException(FileNotFoundException ex){
        System.out.println("【本类】 - FileNotFoundException 异常处理");
        return R.error(300,"文件未找到异常:" + ex.getMessage());
    }


    @ExceptionHandler(Throwable.class)
    public R handleException02(Throwable ex){
        System.out.println("【本类】 - Throwable 异常处理");
        return R.error(500,"其他异常:" + ex.getMessage());
    }

}

@ExceptionHandler只能处理本类的
所以其他类的报错怎么办呢?
使用@ControllerAdvice

@ControllerAdvice

// 全局异常处理器
//@ResponseBody   // 结果还是以JSON的形式写出去
//@ControllerAdvice //告诉SpringMVC,这个组件是专门负责进行全局异常处理的
@RestControllerAdvice   // 合成注解
public class GlobalExceptionHandler {

    /**
     * 如果出现了异常:本类和全局都不能处理,
     * SpringBoot底层对SpringMVC有兜底处理机制;自适应处理(浏览器响应页面、移动端会响应json)
     * 最佳实践:我们编写全局异常处理器,处理所有异常
     * <p>
     * 前端关心异常状态,后端正确业务流程。
     * 推荐:后端只编写正确的业务逻辑,如果出现业务问题,后端通过抛异常的方式提前中断业务逻辑。前端感知异常;
     * <p>
     * 异常处理:
     * 1、
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ArithmeticException.class)
    public R error(ArithmeticException e) {
        System.out.println("【全局】 - ArithmeticException 处理");
        return R.error(500, e.getMessage());
    }


    @ExceptionHandler(BizException.class)
    public R handleBizException(BizException e) {
        Integer code = e.getCode();
        String msg = e.getMsg();
        return R.error(code, msg);
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R methodArgumentNotValidException(MethodArgumentNotValidException ex) {
        //1、result 中封装了所有错误信息
        BindingResult result = ex.getBindingResult();

        List<FieldError> errors = result.getFieldErrors();
        Map<String, String> map = new HashMap<>();
        for (FieldError error : errors) {
            String field = error.getField();
            String message = error.getDefaultMessage();
            map.put(field, message);
        }

        return R.error(500, "参数错误", map);
    }

    // 最终的兜底
    @ExceptionHandler(Throwable.class)
    public R error(Throwable e) {
        System.out.println("【全局】 - Exception处理" + e.getClass());
        return R.error(500, e.getMessage());
    }

}

异常处理优先级

  • 本类 > 全局
  • 精确 > 模糊
    如果出现了异常,本类和全局都不能处理,SpringMVC会兜底处理机制: 自适应处理(什么样的客户端返回什么,要是浏览器就返回一个错误页面,要是客户端,比如Postman,返回json)
    实际上做项目的时候:我们编写全局异常处理器,处理所有异常

最终的异常处理方式

前端关心异常状态
后端正确业务流程
推荐:后端只编写正确的业务逻辑,如果出现业务问题,后端通过抛异常的方式提前中断业务逻辑。前端感知异常;
定义一个业务异常


/**
 * 业务异常
 * 大型系统出现以下异常:异常处理文档,固化
 * 1、订单  1xxxx
 *      10001 订单已关闭
 *      10002 订单不存在
 *      10003 订单超时
 *      .....
 * 2、商品  2xxxx
 *       20001 商品已下架
 *       20002 商品已售完
 *       20003 商品库存不足
 *       ......
 * 3、用户
 *      30001 用户已注册
 *      30002 用户已登录
 *      30003 用户已注销
 *      30004 用户已过期
 *
 * 4、支付
 *      40001 支付失败
 *      40002 余额不足
 *      40003 支付渠道异常
 *      40004 支付超时
 *
 * 5、物流
 *      50001 物流状态错误
 *      50002 新疆得加钱
 *      50003 物流异常
 *      50004 物流超时
 *
 * 异常处理的最终方式:
 * 1、必须有业务异常类:BizException
 * 2、必须有异常枚举类:BizExceptionEnume  列举项目中每个模块将会出现的所有异常情况
 * 3、编写业务代码的时候,只需要编写正确逻辑,如果出现预期的问题,需要以抛异常的方式中断逻辑并通知上层。
 * 4、全局异常处理器:GlobalExceptionHandler;  处理所有异常,返回给前端约定的json数据与错误码
 */

@Data
public class BizException extends RuntimeException {

    private Integer code; //业务异常码
    private String msg; //业务异常信息
    public BizException(Integer code, String message) {
        super(message);
        this.code = code;
        this.msg = message;
    }

    public BizException(BizExceptionEnume exceptionEnume) {
        super(exceptionEnume.getMsg());
        this.code = exceptionEnume.getCode();
        this.msg = exceptionEnume.getMsg();
    }
}

为了便于管理,我们把所有的异常码和异常信息写一个枚举类。

public enum BizExceptionEnume {

    // ORDER_xxx:订单模块相关异常
    // PRODUCT_xxx:商品模块相关异常
    // 动态扩充.....

    ORDER_CLOSED(10001, "订单已关闭"),
    ORDER_NOT_EXIST(10002, "订单不存在"),
    ORDER_TIMEOUT(10003, "订单超时"),
    PRODUCT_STOCK_NOT_ENOUGH(20003, "库存不足"),
    PRODUCT_HAS_SOLD(20002, "商品已售完"),
    PRODUCT_HAS_CLOSED(20001, "商品已下架");

    @Getter
    private Integer code;
    @Getter
    private String msg;


    private BizExceptionEnume(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }


}

然后在我们的全局异常处理器中处理我们的业务异常

 @ExceptionHandler(BizException.class)
    public R handleBizException(BizException e) {
        Integer code = e.getCode();
        String msg = e.getMsg();
        return R.error(code, msg);
    }

在业务中就可以这样用了。


    @Override
    public void updateEmp(Employee employee) {

        //防null处理。考虑到service是被controller调用的;
        //controller层传过来的employee 的某些属性可能为null,所以先处理一下
        //怎么处理?
        Long id = employee.getId();
        if(id == null){ //页面没有带id
            //中断的业务的时候,必须让上层及以上的链路知道中断原因。推荐抛出业务异常
            throw new BizException(BizExceptionEnume.ORDER_CLOSED);
        }
        ……

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

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

相关文章

EasyAR自定义相机RTSP视频流(CustomCamera)

EasyAR可以使用视频源作为输入源&#xff0c;官方给出了示例和文档&#xff0c;但是对于大部分Unity开发人员来说看了文档还是一头雾水。 在Android Studio中将custom-camera.jar添加libs中&#xff0c;就可以查看源代码了 分析其源代码&#xff0c;主要是ExternalCameraSampl…

【linux 多进程并发】linux下使用常见命令,来解析进程家族体系脉络

0101 Linux进程 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 0101 Li…

ASP.NET Core 打包net8.0框架在Linux CentOS7上部署问题

问题1 libstdc.so.6版本过低。 CentOS7默认安装的gcc版本太低&#xff0c;达不到.net8的启动条件。 /lib64/libstdc.so.6: version GLIBCXX_3.4.20’ not found (required by ./IDT_net) /lib64/libstdc.so.6: version GLIBCXX_3.4.21’ not found (required by ./IDT_net) 解…

恢复丢失的数据:恢复数据库网络解决方案

探索恢复数据库网络的深度对于了解现代企业如何防御其数据不断增长的威胁至关重要。在一个时代&#xff0c;数字证据和取证网络安全在法律和商业领域扮演关键角色&#xff0c;这些网络提供的弹性是不可或缺的。深入研究恢复数据库网络的重要性不仅仅是数据保护&#xff0c;它还…

ubuntu安装mysql 8,mysql密码的修改

目录 1.安装mysql 82.查看当前状态3.手动给数据库设置密码mysql5mysql8 4.直接把数据库验证密码的功能关闭掉 1.安装mysql 8 apt install mysql-server-8.0敲 Y 按回车 table 选ok 2.查看当前状态 service mysql status显示active&#xff08;running&#xff09;证明安装成…

媒界:吉利星瑞百炼成钢,持续引领中国汽车价值向上

秋风送爽绘秋色&#xff0c;出行良辰恰逢时。9月28日至9月29日&#xff0c;2024安行中国汽车安全科技公益巡展迎来尾声&#xff0c;安行中国携手吉利汽车&#xff0c;步履轻盈地踏入苏州星湖天街&#xff0c;共同呈献一场融合环保科技前沿、安全驾驶理念与深厚文化底蕴的48小时…

使用jQuery处理Ajax

使用jQuery处理Ajax HTTP协议 超文本传输协议&#xff08;HTTP&#xff0c;HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法 所有的WWW文件都必须遵守这个标准 一次HTTP操作称为一个事务&am…

如何使用 CCF Communicator 框架快速开发设备接口

什么是 CCF Communicator Framework&#xff1f; 通信器框架通过封装 CCF 和设备之间的连接&#xff0c;简化了硬件之间的低级消息处理。 举例来说&#xff0c;考虑一下控制软件和硬件设备之间的连接方式。ASCII 串行连接需要使用 TCP 的套接字连接、用于处理设备发送/接收的…

肺癌类器官培养研究概述

前 言 2023年是类器官被《Science》杂志评为年度十大技术的10周年。10年后类器官技术发展迅猛&#xff0c;犹如一颗璀璨的明珠&#xff0c;不断的为生命科学研究揭示新的奥秘&#xff0c;推动生物医学领域不断前行。肺类器官培养条件也在不断完善&#xff0c;在基础和临床研究…

MySQL面试知识汇总

学习链接 创建索引有哪些注意点&#xff1f; 索引应该建在查询频繁的字段&#xff0c;比如where查询、order排序索引的个数应该适量&#xff08;最多64个&#xff09;&#xff0c;索引需要占用空间&#xff0c;更新时也需要维护区分度低的字段&#xff0c;例如性别&#xff0c…

声阔头戴式耳机怎么样?西圣、jBL、声阔头戴式耳机终极pk测评推荐

我们深知&#xff0c;一款优秀的头戴式耳机&#xff0c;不仅仅是音乐的传递者&#xff0c;更是用户情感与个性的延伸。因此&#xff0c;在设计之初&#xff0c;便将极致的佩戴舒适度视为核心追求&#xff0c;通过人体工学的精准设计与优质材料的精心挑选&#xff0c;力求让每一…

Linux 配置与管理 SWAP(虚拟内存)

Linux 配置与管理 SWAP(虚拟内存&#xff09; 一、作用二、创建交换文件&#xff08;以创建一个2GB的交换文件为例&#xff09;1. 创建交换文件2. 设置文件权限2.1. **关于 sudo chmod 600 /root/swapfile 是否一定要执行**2.2. **关于其他用户启动是否没权限用到交换分区** 3.…

大数据电商数仓项目--实战(一)数据准备

第一章 数仓分层 1.1 为什么要分层 1.2 数仓命名规范 1.2.1 表命名 ODS层命名为ods_表名DIM层命名为dim_表名DWD层命名为dwd_表名DWS层命名为dws_表名DWT层命名为dwt_表名ADS层命名为ads_表名临时表命名为tmp_表名 1.2.2 表字段类型 数量类型为bigint金额类型为decimal(16…

猫咪独自在家可以吗?希喂、美的、有哈宠物空气净化器哪款好?

这不是快要国庆了吗&#xff0c;本来计划去旅游的&#xff0c;结果我妈让我假期回家。收拾行李已经很烦了&#xff0c;行李箱旁的猫咪更是让我头疼。我妈因为之前浮毛过敏的事情&#xff0c;禁止我把猫咪再带回家&#xff0c;朋友们也各有计划&#xff0c;甚至连上门喂养都约满…

设备管理与点巡检系统

在现代企业管理中&#xff0c;设备的高效运作至关重要。为此&#xff0c;我们推出了设备管理与点巡检系统&#xff0c;通过自动化管理提升设备使用效率&#xff0c;保障生产安全。 系统特点 设备全生命周期管理 系统涵盖设备的各个阶段&#xff0c;从设备管理、点检、巡检、保…

计算曲线5s1-2的斜率

在行列可自由变换的条件下&#xff0c;平面上的5点结构只有34个 这次将5点结构通过结构加法化成2点结构5s1-4-3-2&#xff0c;并比较5s1-4-3-2的变化规律。 (A,B)---6*n*2---(0,1)(1,0) 分类A和B&#xff0c;A是34个5点结构&#xff0c;让B全是0。当收敛误差为7e-4&#xff0…

Netty源码解析-响应式实现(Reactor模式)

Netty基本介绍&#xff0c;参考 Netty与网络编程 1、Netty如何支持Reactor模式 1.1 主从Reactor模式 实现这种模式需要定义两个EventLoopGroup&#xff0c;bossGroup就是mainReactor&#xff0c; workerGroup就是subReactor&#xff0c; 接着我们进入下图的b.group方法 1.…

Tomcat部署及其优化

目录 一、Tomcat概述 二、Tomcat的组成 三、Tomcat请求过程 四、Tomcat服务部署 五、/usr/local/tomcat/目录下的主要目录说明 六、Tomcat虚拟主机配置 七、Tomcat优化 1.Tomcat配置文件参数优化 2.Tomcat JVM优化 一、Tomcat概述 Tomcat是基于java语言开发&#xff0c…

传知代码-轻量注意力网络实现苹果叶片识别

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 引言 该系统基于EfficientNet与多头自注意力机制&#xff0c;构建了一个高效、精准的苹果叶片识别模型&#xff0c;能够对不同种类的苹果叶片进行准确分类。通过结合EfficientNet的强大特征提取能力和多头注意力…

Ks渲染做汽车动画吗?汽车本地渲染与云渲染成本分析

Keyshot是一款强大的实时光线追踪和全域光渲染软件&#xff0c;它确实可以用于制作汽车动画&#xff0c;包括汽车模型的渲染和动画展示。Keyshot的动画功能允许用户创建相机移动、物体变化等动态效果&#xff0c;非常适合用于汽车动画的制作。 至于汽车动画的渲染成本&#xff…