Spring Boot中的全局异常处理:@RestControllerAdvice的应用
创始人
2024-11-16 02:38:40
0

在现代Web开发中,异常处理是一个不可或缺的部分。良好的异常处理不仅能提高系统的健壮性,还能提升用户体验。在Spring Boot中,全局异常处理的实现可以通过使用@RestControllerAdvice注解来完成。本文将详细介绍如何使用@RestControllerAdvice@ExceptionHandler来统一处理异常,并给出具体的实现示例。

1. @RestControllerAdvice概述

@RestControllerAdvice是Spring MVC提供的一个功能强大的注解,用于全局处理控制器中的异常。它相当于@ControllerAdvice@ResponseBody的组合,可以用于定义以下三种功能:

  1. @ExceptionHandler:处理特定的异常,并将响应返回给前端。
  2. @InitBinder:预处理Web请求数据的绑定。
  3. @ModelAttribute:将数据绑定到模型中,以便在控制器的@RequestMapping方法中使用。

@RestControllerAdvice自动被Spring的组件扫描机制检测到,若应用通过MVC命令空间或MVC Java编程方式配置,该功能默认自动开启。

2. 实现全局异常处理

在实现全局异常处理时,我们通常会定义一个异常处理类,这个类中包含多个异常处理方法,每个方法对应一种或多种异常类型。下面是一个典型的实现示例。

2.1 全局异常处理器

import com.sugon.cloud.lowcode.result.ReturnResult; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.MyBatisSystemException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestControllerAdvice;  import javax.naming.AuthenticationException; import javax.servlet.http.HttpServletRequest;  import static com.sugon.cloud.lowcode.constants.SplitCharacter.LEFT_PARENTHESES; import static com.sugon.cloud.lowcode.constants.SplitCharacter.RIGHT_PARENTHESES; import static com.sugon.cloud.lowcode.result.CodeMessageEnum.*;  @RestControllerAdvice @Slf4j public class GlobalExceptionHandler {    @ExceptionHandler(value = BizException.class)   @ResponseBody   public ReturnResult bizExceptionHandler(HttpServletRequest req, BizException e) {     log.error("发生业务异常: {}, 请求接口: {}", e.getMessage(), req.getRequestURI());     return ReturnResult.error(e.getCode(), e.getMessage());   }    @ExceptionHandler(value = NullPointerException.class)   @ResponseBody   public ReturnResult exceptionHandler(HttpServletRequest req, NullPointerException e) {     log.error("空指针异常信息: {}, 请求接口: {}", e, req.getRequestURI());     return ReturnResult.error(         NULL_POINT_ERROR_EXCEPTION.getCode(),         NULL_POINT_ERROR_EXCEPTION.getMessage()             + RIGHT_PARENTHESES             + e.getMessage()             + LEFT_PARENTHESES);   }    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)   @ResponseBody   public ReturnResult methodNotSupportedExceptionHandler(HttpServletRequest req, Exception e) {     log.error("请求方法异常信息: {},请求接口: {}", e, req.getRequestURI());     return ReturnResult.error(         REQUEST_METHOD_ERROR.getCode(),         REQUEST_METHOD_ERROR.getMessage() + RIGHT_PARENTHESES + e.getMessage() + LEFT_PARENTHESES);   }    @ExceptionHandler(value = MyBatisSystemException.class)   @ResponseBody   public ReturnResult sqlSyntaxErrorExceptionHandler(HttpServletRequest req, Exception e) {     log.error("MyBatis系统异常信息: {},请求接口: {}", e, req.getRequestURI());     return ReturnResult.error(         INNER_FRAME_EXCEPTION.getCode(),         INNER_FRAME_EXCEPTION.getMessage() + RIGHT_PARENTHESES + e.getMessage() + LEFT_PARENTHESES);   }    @ExceptionHandler(value = AuthenticationException.class)   public ReturnResult incorrectCredentialsException(       HttpServletRequest request, AuthenticationException e) {     log.error("用户名或密码不正确: {}, 请求接口: {}", e, request.getRequestURI());     return ReturnResult.error(USER_CREDENTIALS_ERROR);   }    @ExceptionHandler(value = UserException.class)   public ReturnResult incorrectUserException(HttpServletRequest request, UserException e) {     log.error("用户信息异常: {}, 请求接口: {}", e, request.getRequestURI());     return ReturnResult.error(e.getCode(), e.getMessage());   }    @ExceptionHandler(value = Exception.class)   @ResponseBody   public ReturnResult exceptionHandler(HttpServletRequest req, Exception e) {     e.printStackTrace();     log.error("未知异常: {}, 请求接口: {}", e, req.getRequestURI());     return ReturnResult.error(         INTERNAL_SERVER_ERROR.getCode(),         INTERNAL_SERVER_ERROR.getMessage() + RIGHT_PARENTHESES + e.getMessage() + LEFT_PARENTHESES);   } } 

2.2 自定义业务异常类

import com.sugon.cloud.lowcode.result.BaseResultInterface; import com.sugon.cloud.lowcode.result.CodeMessageEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty;  @ApiModel(description= "业务异常数据") public class BizException extends RuntimeException implements BaseResultInterface {      private static final long serialVersionUID = 1L;      @ApiModelProperty(value = "错误码")     private String code;      @ApiModelProperty(value = "错误信息")     private String message;      public BizException() {         super();     }      public BizException(CodeMessageEnum codeMessageEnum) {         super(codeMessageEnum.getCode());         this.code = codeMessageEnum.getCode();         this.message = codeMessageEnum.getMessage();     }      public BizException(CodeMessageEnum codeMessageEnum, Throwable cause) {         super(codeMessageEnum.getCode(), cause);         this.code = codeMessageEnum.getCode();         this.message = codeMessageEnum.getMessage();     }      public BizException(CodeMessageEnum codeMessageEnum, String message, Throwable cause) {         super(codeMessageEnum.getCode(), cause);         this.code = codeMessageEnum.getCode();         this.message = message;     }      public BizException(String message) {         super(message);         this.message = message;     }      public BizException(String code, String message) {         super(code);         this.code = code;         this.message = message;     }      public BizException(String code, String message, Throwable cause) {         super(code, cause);         this.code = code;         this.message = message;     }      @Override     public Throwable fillInStackTrace() {         return this;     }      @Override     public String getCode() {         return this.code;     }      @Override     public String getMessage() {         return this.message;     } } 

3. 统一返回格式

在上述代码中,所有的异常处理方法返回的是ReturnResult对象,它封装了返回给前端的数据。ReturnResult类的设计使得前端可以统一解析和展示错误信息。

3.1 返回结果类

import com.alibaba.fastjson.JSONObject; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter;  import static com.sugon.cloud.lowcode.result.CodeMessageEnum.*;  @Setter @Getter @ApiModel(description= "返回响应数据") public class ReturnResult {    @ApiModelProperty(value = "状态码")   private String code;    @ApiModelProperty(value = "响应信息")   private String message;    @ApiModelProperty(value = "响应对象")   private T result;    @ApiModelProperty(value = "是否成功")   private boolean success = true;    public ReturnResult() {}    public ReturnResult(CodeMessageEnum codeMessageEnum) {     this.code = codeMessageEnum.getCode();     this.message = codeMessageEnum.getMessage();   }    public static ReturnResult success() {     return success(null);   }    public static  ReturnResult success(T data) {     return success(SUCCESS, data);   }    public static  ReturnResult loginSuccess(T data) {     return success(SUCCESS_LOGIN, data);   }    public static ReturnResult loginOutSuccess() {     return success(SUCCESS_LOGOUT, null);   }    private static  ReturnResult success(CodeMessageEnum codeMessageEnum, T data) {     ReturnResult result = new ReturnResult<>();     result.setCode(codeMessageEnum.getCode());     result.setMessage(codeMessageEnum.getMessage());     result.setResult(data);     return result;   }    public static ReturnResult error(CodeMessageEnum codeMessageEnum) {     return error(codeMessageEnum.getCode(), codeMessageEnum.getMessage());   }    public static ReturnResult error(CodeMessageEnum codeMessageEnum, String message) {     return error(codeMessageEnum.getCode(), message);   }    public static ReturnResult error(String code, String message) {     ReturnResult result = new ReturnResult();     result.setCode(code);     result.setMessage(message);     result.setSuccess(false);     return result;   }    @Override   public String toString() {     return JSONObject.toJSONString(this);   } } 

4. 总结

通过@RestControllerAdvice@ExceptionHandler,我们可以在Spring Boot应用中实现全局异常处理,统一管理和处理所有异常。这样不仅可以

减少重复代码,还能使代码更加整洁,提高可维护性。同时,通过统一的返回格式,前端处理响应数据时也能更加方便。

希望这篇文章对您在Spring Boot中实现全局异常处理有所帮助。如有任何问题或建议,欢迎交流探讨。

相关内容

热门资讯

第九分钟辅助!天天爱柳州辅助器... 天天爱柳州辅助器是一款可以让一直输的玩家,快速成为一个“必胜”的ai辅助神器,有需要的用户可以加我微...
热门推荐!微信小程序蜀山辅助器... 热门推荐!微信小程序蜀山辅助器免费下载(辅助)外挂辅助开挂插件(有挂秘诀)-哔哩哔哩;最新版2026...
第4分钟普及!奇迹陕西辅助器(... 第4分钟普及!奇迹陕西辅助器(透视)原来真的是有挂脚本(推荐开挂软件);奇迹陕西辅助器免费下载原版,...
第八分钟讲解!越乡游金花辅助,... 第八分钟讲解!越乡游金花辅助,九酷众游辅助,细节方法(有挂实锤)-哔哩哔哩1、下载安装好越乡游金花辅...
透视软件!浙江宝宝游戏辅助工具... 透视软件!浙江宝宝游戏辅助工具(辅助)外挂开挂辅助插件(了解有挂)-哔哩哔哩;是一款可以让一直输的玩...
第5分钟发现!桃乐甘肃麻将下载... 《第5分钟发现!桃乐甘肃麻将下载辅助器(辅助)原来有挂软件(必看开挂工具)》 桃乐甘肃麻将下载辅助器...
第8分钟了解!河洛刚次辅助,温... 第8分钟了解!河洛刚次辅助,温州茶苑辅助软件,详细教程(有挂攻略)-哔哩哔哩;无需打开直接搜索加薇1...
热点讨论!新二号辅助软件下载(... 热点讨论!新二号辅助软件下载(辅助)外挂辅助开挂软件(有挂教程)-哔哩哔哩;是一款可以让一直输的玩家...
8分钟解说!网易亲友圈辅助(开... 8分钟解说!网易亲友圈辅助(开挂)原来有挂平台(必看开挂安装);小薇(透视辅助)致您一封信;亲爱网易...
第5分钟开挂!如何在哈灵上辅助... 第5分钟开挂!如何在哈灵上辅助,决战卡五星辅助看牌器,解说技巧(有挂方略)-哔哩哔哩 了解更多开挂安...