优雅的处理sping项目全局异常

news2024/10/6 20:37:28

全局异常处理

为了达到系统的各个模块中都能够共用同一个异常处理逻辑,避免代码重复和错误。在Spring框架中,可以通过全局异常处理来捕获应用程序中抛出的异常,并根据需要进行处理。

@ControllerAdvice

@ControllerAdvice是Spring MVC框架中的一个注解,用于定义一个全局的异常处理器和绑定响应数据的方法。

当Spring MVC中的Controller抛出异常时,它会查找@ControllerAdvice注解标注的类,然后调用其中匹配异常类型的方法来处理异常。这些方法可以返回一个ModelAndView对象、一个ResponseEntity对象或者其它任意类型的对象。此外,这些方法也可以通过@ExceptionHandler注解将响应数据绑定到请求中,使其可在视图中渲染。

@ControllerAdvice注解可以用于定义全局的异常处理器,以便在系统的各个模块中都能够共用同一个异常处理逻辑,避免代码重复和错误。例如,在处理Web应用程序的RESTful API时,可以使用@ControllerAdvice注解定义一个异常处理器,以便在出现异常时返回一个统一的错误响应格式。

@ControllerAdvice注解也可以用于定义全局的数据绑定方法,以便在处理请求时,自动将一些公共的响应数据绑定到请求中,避免了在Controller中的方法中的重复绑定。

@ControllerAdvice注解通常用于Web应用程序中,可以与@ExceptionHandler、@InitBinder和@ModelAttribute注解一起使用。

定义全局异常处理类

定义一个全局异常处理类,通过@ControllerAdvice注解,其中定义了匹配异常类型的方法来处理异常,用注册@ExceptionHandler({Throwable.class})注解方法,Throwable.class为匹配的异常类型。

/**
 * 全局异常.
 *
 * @author <a href="mailto:felix@gmail.com">lht</a>
 * @date 2023/4/17 16:27
 * @since 1.0.0
 **/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private MessageSource messageSource;

    /**
     * Throwable异常处理.
     *
     * @param e       e
     * @param request request
     * @return ResponseEntity
     */
    @ExceptionHandler({Throwable.class})
    public ResponseEntity<R> handleGlobalExceptionResponse(final Throwable e, final HttpServletRequest request) {
        log.error("handleGlobalException: ", e);
        return ExceptionHandlerUtil.handleGlobalException(this.messageSource);
    }

    /**
     * BusinessException异常处理.
     *
     * @param businessException businessException
     * @param request           request
     * @return ResponseEntity
     */
    @ExceptionHandler({BusinessException.class})
    public ResponseEntity<R> handleServiceExceptionResponse(final BusinessException businessException, final HttpServletRequest request) {
        return ExceptionHandlerUtil.handleBusinessException(this.messageSource, businessException);
    }

    /**
     * MethodArgumentNotValidException异常处理.
     *
     * @param e       e
     * @param request request
     * @return result
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ResponseEntity<R> handleMethodArgumentNotValidException(final MethodArgumentNotValidException e, final HttpServletRequest request) {
        String key = ((ObjectError) e.getBindingResult().getAllErrors().get(0)).getDefaultMessage();
        return ExceptionHandlerUtil.handleBusinessException(this.messageSource, new BusinessException(key));
    }

}

ExceptionHandlerUtil工具类,可以将国际化配置中的内容通过MessageSource获取后解析后返回给前端,messageSource的key为自定义异常中的messageKey,参考后面的代码BusinessException。

/**
 * 全局异常工具类.
 *
 * @author <a href="mailto:felix@gmail.com">lht</a>
 * @date 2023/4/17 16:27
 * @since 1.0.0
 **/
@Slf4j
public class ExceptionHandlerUtil {

    private static final String RES_DEFAULT_ERROR_MSG = "global.server.internal.error";

    public ExceptionHandlerUtil() {
    }

    /**
     * 全局异常.
     *
     * @param msgSource 国际化配置
     * @return responseEntity
     */
    public static ResponseEntity<R> handleGlobalException(final MessageSource msgSource) {
        String msgValue = getGlobalMessage(RES_DEFAULT_ERROR_MSG);

        try {
            msgValue = msgSource.getMessage(RES_DEFAULT_ERROR_MSG, (Object[]) null, (Locale) null);
        } catch (NoSuchMessageException var4) {
            log.warn("解析messageKey:{} 全局异常错误信息:{}", RES_DEFAULT_ERROR_MSG, var4.getMessage());
        }

        return responseEntity(msgValue);
    }

    /**
     * businessException异常处理.
     *
     * @param msgSource         国际化配置
     * @param businessException 异常
     * @return responseEntity
     */
    public static ResponseEntity<R> handleBusinessException(final MessageSource msgSource, final BusinessException businessException) {
        String msgValue = getDefaultMessage(businessException.getMessageKey());

        try {
            msgValue = msgSource.getMessage(businessException.getMessageKey(), businessException.getValues(), (Locale) null);
        } catch (NoSuchMessageException var) {
            log.warn("BusinessException-解析messageKey:{} BusinessException-异常错误信息:{}", businessException.getMessageKey(), var.getMessage());
        }
        return responseEntity(msgValue);
    }

    /**
     * responseEntity.
     *
     * @param msgValue 配置的值
     * @return responseEntity
     */
    private static ResponseEntity<R> responseEntity(final String msgValue) {
        String[] values = msgValue.split(";");
        if (values.length < 3) {
            values = new String[]{String.valueOf(400), "system.unknown", "400"};
        }
        ResponseEntity<R> resultResponseEntity = new ResponseEntity(R.error(0, values[2] == null ? "400" : values[2], values[1] == null ? RES_DEFAULT_ERROR_MSG : values[1]), HttpStatus.
                //默认取400
                        valueOf(Integer.parseInt(values[0])));
        return resultResponseEntity;
    }

    /**
     * businessException默认的message.
     *
     * @param messageKey messageKey
     * @return messageKey
     */
    private static String getDefaultMessage(final String messageKey) {
        return "400;" + messageKey + ";" + "400";
    }

    /**
     * 全局异常message.
     *
     * @param messageKey
     * @return messageKey
     */
    private static String getGlobalMessage(final String messageKey) {
        return "500;" + messageKey + ";" + "500";
    }
}

也可以自定义异常去匹配处理,如上面的@ExceptionHandler({BusinessException.class})的方法,BusinessException就是自定义异常处理类:


/**
 * @author <a href="mailto:felix@gmail.com">lht</a>
 * @date 2023/4/17 14:39
 * @since 1.0.0
 **/
public class BusinessException extends CommonException {

    public BusinessException(final String messageKey, final Object... values) {
        super(messageKey, values);
    }

    public BusinessException(final String messageKey) {
        super(messageKey);
    }

    public BusinessException(final Throwable cause, final String messageKey, final Object... values) {
        super(cause, messageKey, values);
    }

    public BusinessException(final Throwable cause, final String messageKey) {
        super(cause, messageKey);
    }

}

当项目抛出BusinessException,会匹配到@ExceptionHandler({BusinessException.class})注解的方法,BusinessException的messageKey可以自定义,并且可以配置到国际化配置中。

示例

定义一个接口,抛出异常BusinessException。

this.test.error是自定义配置在配置文件中的key,配置中的ASCII码含义是这是一个错误码测试,value后面的400001为返回的code码。

请求后返回

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

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

相关文章

TCP CUBIC 动力学

曾陪经理一起面试&#xff0c;问过一个问题&#xff1a; CUBIC 的公式&#xff1a; W ( x ) C ( x − K ) 3 W m a x W(x)C(x−K)^3W_{max} W(x)C(x−K)3Wmax​ 其中 x 是什么意思&#xff1f; 本意是想候选人回答 “x 是绝对时间”&#xff0c;然后我会接着问 “这个 x …

[SWPUCTF] 2021新生赛之(NSSCTF)刷题记录 ②

[SWPUCTF] 2021 新生赛&#xff08;NSSCTF刷题记录wp&#xff09; [SWPUCTF 2021 新生赛]no_wakeup[鹤城杯 2021]easy_crypto[suctf 2019]EasySQL[ZJCTF 2019]NiZhuanSiWei[强网拟态 2021]拟态签到题[BJDCTF 2020]easy_md5[SWPUCTF 2021 新生赛]easyupload3.0[SWPUCTF 2021 新生…

Python解决微软Microsoft的登录机器人验证

前言 本文是该专栏的第8篇,结合优质项目案例,让你精通使用Pyppeteer,后面会持续分享Pyppeteer的干货知识,记得关注。 在注册微软Microsoft账号或者注册outlook邮箱账号的时候,会遇到如下机器人验证: 是的,你可能第一眼看到这个验证页面,首先会想到是定位它的页面元素N…

数据结构各结构特点(数组、链表、栈、队列、树)

目录 一、数组 二、链表 三、栈 四、队列 五、树 1.二叉树 2.二叉查找树 3.平衡二叉树&#xff08;AVL树&#xff09; 4.红黑树 六、总结&#xff1a; 1.红黑树和平衡二叉树的区别&#xff1a; 2.为什么有了数组和链表还要引入二叉树&#xff1f; 3.为什么有了二叉树…

【Linux】从机I/O线程报错

一、报错问题 I/O线程报错 查看/var/log/mysqld.d日志&#xff0c;查看报错&#xff1b; 在从机&#xff0c;telnet主机的3306端口显示拒绝连接&#xff1b; 并且从机mysql登录用户密码问题&#xff0c;密码输入正确但是报错【ERROR 1045 (28000): Access denied for user root…

软件开发中的DevOps实践

一、引言 在软件开发领域&#xff0c;为了满足用户需求、提升产品质量、缩短产品上线时间&#xff0c;DevOps已经成为一种流行的开发实践方式。本文将从什么是DevOps、DevOps的理念、DevOps的价值、DevOps的实践等方面详细介绍DevOps在软件开发中的实践。 二、什么是DevOps …

python爬虫原理及源码解析(入门)

目录 一、爬虫是什么&#xff1f;二、爬虫的基本原理三、HTTP协议与响应4、爬虫实现源码 一、爬虫是什么&#xff1f; ​ 如果将互联网比作一张大的蜘蛛网&#xff0c;数据便是存放在蜘蛛网的各个节点&#xff0c;而爬虫就是一只小蜘蛛&#xff0c;沿着网络抓取自己的猎物(数据…

用spring-boot-starter实现事务的统一配置

一、前言 微服务架构下&#xff0c;多个微服务都需要事务操作&#xff0c;如果在每个微服务下都从头配置事务&#xff0c;将非常繁锁。事务配置具有高度的一致性&#xff0c;可以抽取出来&#xff0c;制作starter&#xff0c;在需要配置事务的服务中引入starter依赖即可。 采用…

NFS(UOS)

appsrv 172.16.146.11 strogesrv 172.16.146.53 共享/data/share目录 用于存储app主机的web数据 仅允许stora访问该共享 安装nfs apt install nfs-common nfs-kernel-server -y mkdir /data/share /data/share 172.16.146.50(rw,sync,no_root_squash,insecure) 重启服…

志特转债上市价格预测

志特转债 基本信息 转债名称&#xff1a;志特转债&#xff0c;评级&#xff1a;A&#xff0c;发行规模&#xff1a;6.14033亿元。 正股名称&#xff1a;志特新材&#xff0c;今日收盘价&#xff1a;35.6元&#xff0c;转股价格&#xff1a;41.08元。 当前转股价值 转债面值 / …

微服务学习高级篇【5】之服务异步通信(rabbitmq的高级特性)

文章目录 环境准备&#xff1a;MQ部署【docker环境】消息可靠性生产者消息确认项目配置定义Return回调和ConfirmCallback 消息持久化交换机持久化队列持久化消息持久化 消费者消息确认none模式演示 消费失败重试机制本地重试失败策略 总结 死信交换机初识死信交换机死信交换机接…

【DHCP原理与配置】

目录 一、了解DHCP服务使用DHCP的好处DHCP的分配方式 二、DHCP的租约过程传输协议端口DHCP的IP地址自动获取工作原理 三、配置DHCP服务器安装dhcp查看配置文件根据配置文件提示查看相关文档 四、模拟外网和内网互通进入主机1的设置进入主机2的设置复制dhcp文件&#xff0c;修改…

Nginx 优化与防盗链

Ngnix优化主要有两种&#xff0c;一种是配置上的优化&#xff0c;一种是内核上的优化 实验准备&#xff1a;安装好一台Nginx服务器&#xff0c;IP&#xff1a;192.168.126.22&#xff0c;域名&#xff1a;www.accp.com 浏览器访问nginx服务器此时F12查看网页信息&#xff0c;可…

MySQL之表的约束

目录 一 空属性 定义 如何设置 示例 影响&#xff1a; 二 默认值 定义 示例 影响&#xff1a; 三 列描述 定义 示例 影响&#xff1a; 四 zerofill 定义&#xff1a; 示例&#xff1a; 影响&#xff1a; 五 主键 定义 主键的性质是什么&#xff1a; 为什么要…

C++——一种特殊的二叉搜索树之红黑树

目录 1 红黑树的概念2 红黑树的性质3 红黑树节点的定义4 红黑树的插入操作情况一: cur为红&#xff0c;p为红&#xff0c;g为黑&#xff0c;u存在且为红。情况二: cur为红&#xff0c;p为红&#xff0c;g为黑&#xff08;不存在连续的红结点&#xff09;&#xff0c;u不存在/u存…

设计模式 -- 适配器模式

前言 月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂) 央是一片海洋,海乃百川,代表着一块海绵(吸纳万物) 泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出) 月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容 希望大家一起坚持这个过程,也同…

第五篇 Spring 集合注入、作用域

《Spring》篇章整体栏目 ————————————————————————————— 【第一章】spring 概念与体系结构 【第二章】spring IoC 的工作原理 【第三章】spring IOC与Bean环境搭建与应用 【第四章】spring bean定义 【第五章】Spring 集合注入、作用域 【第六章】…

时间序列分析卫星重力梯度观测值

阚昊宇 1 时间序列图 导入数据&#xff0c;共2880历元&#xff08;86370 s&#xff09;数据&#xff0c;取前2400历元&#xff08;72000 s&#xff09;数据作为训练集&#xff0c;后480历元作为测试集。将训练集绘制时间序列图如下图 1红色线所示&#xff0c;可见明显的自相关…

elementUI-el-table组件使用总结

一、背景 vue2项目中用到el-table这个组件&#xff0c;但基础的功能不够用&#xff0c;所以需要自定义 二、表头自定义 比如要让表头展现出下面的形式&#xff1a; 只需使用 slot"header" slot-scope"scope" 对插槽进行定义&#xff0c;并绑定变量 <…

快手视频艾特实操教学分享,什么是艾特脚本,评论区艾特引流脚本讲解!

大家好我是你们的小编一辞脚本&#xff0c;今天给大家分享新的知识&#xff0c;很开心可以在CSDN平台分享知识给大家,很多伙伴看不到代码我先录制一下视频 在给大家做代码&#xff0c;给大家分享一下快手艾特脚本的知识和视频演示 不懂的小伙伴可以认真看一下&#xff0c;我们…