深入理解Java Spring中的全局异常处理:以Reggie项目为例

在Java Spring开发中,异常处理是非常关键的一部分。优雅地处理异常不仅可以提升用户体验,还能帮助开发者快速定位问题。本文将通过Reggie项目中的一个实例,深入探讨如何在Spring中使用@ControllerAdvice@ExceptionHandler实现全局异常处理。

项目背景

Reggie是一个基于Spring框架的Web应用,它可能包含多个控制器(Controller)来处理不同的业务逻辑。在这些控制器中,我们可能会遇到各种异常,如数据库约束违规、自定义业务异常等。为了统一处理这些异常并返回给前端统一的错误格式,我们引入了全局异常处理的概念。

全局异常处理类

在Reggie项目中,我们有一个名为GlobalExceptionHandler的类,它使用了@ControllerAdvice注解。这个注解表明该类是一个增强类,它可以对Controller进行全局增强。具体来说,它可以用来处理全局的异常、绑定数据、处理返回结果等。

注解说明

  • @ControllerAdvice(annotations = {RestController.class, Controller.class}): 表示这个增强类会对所有标注了@RestController@Controller的类生效。
  • @ResponseBody: 表示该类中所有方法的返回值都会自动转换为JSON格式响应给前端。
  • @Slf4j: 是Lombok库提供的注解,用于自动生成日志对象,方便记录日志。

异常处理方法

GlobalExceptionHandler类中,我们定义了两个异常处理方法,分别处理SQLIntegrityConstraintViolationExceptionCustomException

  1. exceptionHandler(SQLIntegrityConstraintViolationException ex): 这个方法专门处理数据库完整性约束违反的异常,通常是由于插入了重复的数据导致的。方法内部首先记录异常信息到日志中,然后检查异常信息是否包含"Duplicate entry",如果包含,则提取出重复的数据项并返回给前端一个友好的错误信息;如果不包含,则返回一个"未知错误"的信息。
  2. exceptionHandler(CustomException ex): 这个方法用来处理自定义的业务异常。业务异常通常是在业务逻辑处理过程中发现的,比如数据验证失败等。这个方法同样会记录异常信息到日志中,并直接返回异常信息给前端。

返回结果封装

在上述两个方法中,我们都返回了一个R<String>类型的对象。这通常是一个自定义的响应结果类,用来封装返回给前端的数据。在这个例子中,R类可能包含了一个状态码、消息和数据等字段。通过这种方式,我们可以保证所有返回给前端的数据都有统一的格式,便于前端处理。

总结与扩展

通过GlobalExceptionHandler类,我们可以很方便地实现Spring应用中的全局异常处理。这种方式不仅减少了重复代码,还提高了代码的可维护性和可读性。在实际项目中,我们还可以根据需要对这个类进行扩展,比如添加更多的异常处理方法来处理不同类型的异常,或者在方法内部添加更复杂的逻辑来处理异常情况。

文件源码:

java 复制代码
package com.itheima.reggie.common;

import com.sun.org.glassfish.external.statistics.annotations.Reset;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.sql.SQLIntegrityConstraintViolationException;

/**
 * 全局异常捕获
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 异常处理方法
     * @param ex
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error(ex.getMessage());

        if(ex.getMessage().contains("Duplicate entry")){
            String[] split = ex.getMessage().split(" ");
             String msg=split[2]+"已存在";
             return R.error(msg);
        }
                return R.error("未知错误");
    }

    /**
     * 异常处理方法(删除分类)
     * @param ex
     * @return
     */
    @ExceptionHandler(CustomException.class)
    public R<String> exceptionHandler(CustomException ex){
        log.error(ex.getMessage());

        return R.error(ex.getMessage());
    }
}
相关推荐
腥臭腐朽的日子熠熠生辉7 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian9 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之15 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码35 分钟前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen1 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
绝顶少年2 小时前
Spring Boot 注解:深度解析与应用场景
java·spring boot·后端