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

总结与扩展

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

文件源码:

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());
    }
}


你可能感兴趣的:(java,spring,状态模式)