Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 304|回复: 0

SpringBoot:如何优雅地处理全局异常?

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-2 14:08:49 | 显示全部楼层 |阅读模式

    之前用springboot的时候,只知道捕获异常使用try{}catch,一个接口一个try{}catch,这也是大多数开发人员异常处理的常用方式,虽然屡试不爽,但会造成一个问题,就是一个Controller下面,满屏幕的try{}catch,看着一点都不优雅,一点都不符合小明的气质,憋了这么久,小明今天终于决定对所有异常实施统一处理的方案。

    开发准备

    JDK8、正常的springboot项目

    代码编写

    通用异常处理

    其实Spring系列的项目全局异常处理方式早已存在,只不过我们一直忙于搬砖,很少停下脚步去审视这个日夜与我们相伴的朋友。为了贴合主题,本次主要针对SpringBoot全局异常处理进行举例说明。

    SpringBoot中有一个@ControllerAdvice的注解,使用该注解即表示开启全局异常捕获,接下来我们只需在自定义的方法上使用@ExceptionHandler注解,并定义捕获异常的类型,对这种类型的异常进行统一的处理。

    举个例子:

    假如我们需要针对NullException(空指针异常,是Java程序员最痛恨的异常,没有之一)进行全局处理(如下所示)。

    @RestControllerAdvice
    public class GlobalExceptionHandler {
    		/**
         * 处理空指针的异常
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value =NullPointerException.class)
        public BaseResponseFacade exceptionHandler(HttpServletRequest req, NullPointerException e){
            log.error("发生空指针异常!原因是:",e);
            return ResponseUtil.error(ResponseCode.ERROR);
        }
    }
    

    讷,就这么简单。其他可能发生的异常,都可以以这种方式处理快速处理。此处大家应该表现的十分兴奋,但请不要高兴太早,因为接下来,有更令激动人心的事情。

    自定义异常处理

    自定义一个异常
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.experimental.Accessors;
    
    /**
     * @Description 自定义异常
     * @Date 2019-08-05 15:49
     * @Created by 程序员小明
     */
    @Data
    @AllArgsConstructor
    @Accessors(chain = true)
    public class BizException extends RuntimeException {
        /**
         * 错误码
         */
        protected Integer errorCode;
        /**
         * 错误信息
         */
        protected String errorMsg;
    }
    

    显而易见,这个异常继承了RuntimeException,属于运行时异常。细心的朋友已经发现,我使用了Lombok插件,非常契合今天的主题,给大家简单介绍一下:

    lombok是一个可以帮助我们简化java代码编写的工具类,尤其是简化javabean的编写,即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁(如果使用的IDE是idea,需要安装插件哈)。

    定义过之后,我们就可以和之前处理NullException方式一样处理我们自定义的异常。包括处理其他异常,都是这种方式。直接贴代码。

    @Slf4j
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
        /**
         * 处理自定义的业务异常
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = BizException.class)
        public BaseResponseFacade bizExceptionHandler(HttpServletRequest req, BizException e){
            log.error("发生业务异常!原因是:{}",e.getErrorMsg());
            return ResponseUtil.error(e.getErrorCode(),e.getErrorMsg());
        }
    
        /**
         * 处理空指针的异常
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value =NullPointerException.class)
        public BaseResponseFacade exceptionHandler(HttpServletRequest req, NullPointerException e){
            log.error("发生空指针异常!原因是:",e);
            return ResponseUtil.error(ResponseCode.ERROR);
        }
    
    
        /**
         * 处理其他异常
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value =Exception.class)
        public BaseResponseFacade exceptionHandler(HttpServletRequest req, Exception e){
            log.error("未知异常!原因是:",e);
            return ResponseUtil.error(ResponseCode.INTERNAL_SERVER_ERROR);
        }
    }
    
    

    整个全局异常处理方式核心就是以上介绍这些。下面用一个Demo给大家举个例子

    @GetMapping("/test")
    public BaseResponseFacade test(){
      if(true){
      	throw new BizException(1,"error");
      }
      return ResponseUtil.success();
    }
    

    地址栏请求,进入这个方法后,会抛出异常,此时全局异常生效,就会返回异常处理过后的信息

    {"errorCode":1,"errorMsg":"error","data":null}
    

    到此整个流程都然跑通了。当然,好多地方都可以根据我们自身实际业务情况以此为基础进一步丰富,比如返回数据可以改成跳转某一个具体的页面。这样的出场方式是不是都很优雅?大家有什么问题,期待各位留言。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-4 04:52 , Processed in 0.060867 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表