深入理解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());
    }
}
相关推荐
AI多Agent协作实战派8 小时前
AI多Agent协作系统实战(十七):凌晨4点,我的AI系统在“假装工作“——3个bug同时爆炸的5小时
java·前端·bug
gaolei_eit8 小时前
Java+Ai+vue
java·spring·maven
qq_2518364578 小时前
基于java Web 动漫视频网站毕业论文
java·开发语言·前端
LayZhangStrive8 小时前
JUC相关的函数、注解、变量杂记
java·面试·多线程·juc
玉&心8 小时前
关于配置mcp服务端sse-message-endpoint和sse-endpoint的注意点
spring·springai·mcp
未秃头的程序猿8 小时前
给公司做了个AI客服Agent,用的Spring AI 1.0,3天上线领导拍板了
java·后端·ai编程
曹牧8 小时前
Eclipse 批量文本替换
java·ide·eclipse
程序员清风8 小时前
OpenAI官方发布最新提示词技巧!
java·后端·面试
梅头脑9 小时前
写了3年CRUD,volatile和synchronized的区别还是答不清——直到我画出了这张三性两锁边界图
java
暮暮祈安9 小时前
Celery 新手入门指南
java·数据库·python·flask·httpx