找回密码
 立即注册
首页 业界区 安全 Java 自定义全局异常处理类

Java 自定义全局异常处理类

洪思思 2025-5-31 23:57:52
自定义全局异常处理类:优雅管理应用错误,告别杂乱代码

感觉本篇对你有帮助可以关注一下我的微信公众号(深入浅出谈java),会不定期更新知识和面试资料、技巧!!!
1.png

优点:

自定义全局异常处理类在开发中有以下几个主要用途和好处:

  • 集中管理异常:通过自定义全局异常处理类,可以集中处理应用程序中所有的异常,而不需要在每个控制器中重复编写异常处理逻辑。这有助于代码的整洁性和可维护性。
  • 统一的异常响应:全局异常处理类可以统一格式化异常的返回结果,确保前端接收到的一致性和规范性,这样在处理错误时,用户体验更加友好。
  • 细粒度控制:可以根据不同类型的异常,定制不同的处理方式。例如,可以根据业务逻辑的需要返回不同的状态码和错误信息,方便前端进行处理。
  • 记录日志:在全局异常处理类中,可以统一记录异常信息,便于后续的排查和分析。这有助于提高系统的监控和维护能力。
  • 简化代码:通过自动化处理一些常见的异常(如请求参数异常、认证异常等),可以减少每个处理方法中的异常处理代码,使得业务逻辑更加清晰。
  • 增强安全性:通过统一处理异常,可以有效避免敏感信息(如堆栈跟踪信息等)泄露到客户端,提高了应用程序的安全性。
全局异常处理实现原理


  • @ControllerAdvice:声明全局异常处理类,监控所有Controller的异常。
  • @ExceptionHandler:标注具体处理异常的方法,支持按异常类型匹配。
  • 统一响应体:封装错误码、错误信息、数据等标准结构。
代码实现部分

2.1、定义全局异常处理类
在 Spring Boot 中,可以使用 @ControllerAdvice 注解来定义全局异常处理类
  1. import lombok.extern.slf4j.Slf4j;
  2. import org.springframework.http.HttpStatus;
  3. import org.springframework.web.bind.MethodArgumentNotValidException;
  4. import org.springframework.web.bind.annotation.ControllerAdvice;
  5. import org.springframework.web.bind.annotation.ExceptionHandler;
  6. import org.springframework.web.bind.annotation.ResponseBody;
  7. import org.springframework.web.bind.annotation.ResponseStatus;
  8. /**
  9. * @Classname GlobalExceptionHandlerAdvice
  10. * @Description 自定义全局异常处理类
  11. * @Version 1.0.0
  12. * @Date 2024/6/6 16:02
  13. * @Created by Administrator
  14. */
  15. @Slf4j
  16. @ControllerAdvice
  17. public class GlobalExceptionHandlerAdvice {
  18.     /**-------- 通用异常处理方法 --------**/
  19.     @ExceptionHandler(Exception.class)
  20.     @ResponseBody
  21.     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  22.     public R error(Exception e) {
  23.         e.printStackTrace();
  24.         log.error("全局异常捕获:" + e);
  25.         return R.fail();    // 通用异常结果
  26.     }
  27.     /**-------- 指定异常处理方法 --------**/
  28.     @ExceptionHandler(NullPointerException.class)
  29.     @ResponseBody
  30.     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  31.     public R error(NullPointerException e) {
  32.         e.printStackTrace();
  33.         log.error("全局异常捕获:" + e);
  34.         return R.setResult(ResultCodeEnum.NULL_POINT);
  35.     }
  36.     /**-------- 下标越界处理方法 --------**/
  37.     @ExceptionHandler(IndexOutOfBoundsException.class)
  38.     @ResponseBody
  39.     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  40.     public R error(IndexOutOfBoundsException e) {
  41.         e.printStackTrace();
  42.         log.error("全局异常捕获:" + e);
  43.         return R.setResult(ResultCodeEnum.INDEX_OUT_OF_BOUNDS);
  44.     }
  45.     /**
  46.      * 方法参数校验
  47.      */
  48.     @ExceptionHandler(MethodArgumentNotValidException.class)
  49.     @ResponseBody
  50.     @ResponseStatus(HttpStatus.BAD_REQUEST)
  51.     public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
  52.         log.error(e.getMessage(), e);
  53.         return R.setResult(ResultCodeEnum.PARAM_ERROR).message(e.getBindingResult().getFieldError().getDefaultMessage());
  54.     }
  55.     /**-------- 自定义定异常处理方法 --------**/
  56.     @ExceptionHandler(UserException.class)
  57.     @ResponseBody
  58.     @ResponseStatus(HttpStatus.OK)
  59.     public R error(UserException e) {
  60.         e.printStackTrace();
  61.         log.error("全局异常捕获:" + e);
  62.         return R.fail().message(e.getMessage()).code(e.getCode());
  63.     }
  64. }
复制代码
2.2 自定义定异常处理方法
这里我们可以定义自己的异常方法(UserException 类),可后续在业务代码中使用
  1. /**
  2. * 自定义异常类
  3. *
  4. * @author admin
  5. * @date 2018/10/15
  6. */
  7. public class UserException extends RuntimeException {
  8.     private Integer code;
  9.     public UserException(String message) {
  10.         super(message);
  11.         this.code = ResultCodeEnum.CUSTOM_ERROR.getCode();
  12.     }
  13.     public UserException(Integer code, String message) {
  14.         super(message);
  15.         this.code = code;
  16.     }
  17.     public UserException(ResultCodeEnum resultCodeEnum) {
  18.         super(resultCodeEnum.getMessage());
  19.         this.code = resultCodeEnum.getCode();
  20.     }
  21.     public String toString() {
  22.         return "UserException{code=" + this.code + ", message=" + this.getMessage() + '}';
  23.     }
  24.     public Integer getCode() {
  25.         return this.code;
  26.     }
  27.     public void setCode(final Integer code) {
  28.         this.code = code;
  29.     }
  30.     public boolean equals(final Object o) {
  31.         if (o == this) {
  32.             return true;
  33.         } else if (!(o instanceof UserException)) {
  34.             return false;
  35.         } else {
  36.             UserException other = (UserException)o;
  37.             if (!other.canEqual(this)) {
  38.                 return false;
  39.             } else {
  40.                 Object this$code = this.getCode();
  41.                 Object other$code = other.getCode();
  42.                 if (this$code == null) {
  43.                     if (other$code != null) {
  44.                         return false;
  45.                     }
  46.                 } else if (!this$code.equals(other$code)) {
  47.                     return false;
  48.                 }
  49.                 return true;
  50.             }
  51.         }
  52.     }
  53.     protected boolean canEqual(final Object other) {
  54.         return other instanceof UserException;
  55.     }
  56.     public int hashCode() {
  57.         int result = 1;
  58.         Object $code = this.getCode();
  59.         result = result * 59 + ($code == null ? 43 : $code.hashCode());
  60.         return result;
  61.     }
  62. }
复制代码
2.3、状态码枚举类
定义要用的状态枚举类,可做到统一的返回格式,这里也是可以自己定义和修改,只不过我提供的 UserException有用到该枚举类
  1. public enum ResultCodeEnum {
  2.     SUCCESS(true, 0, "成功"),
  3.     UNKNOWN_ERROR(false, 999999, "未知错误"),
  4.     DAO_INSERT_ERROR(false, 100000, "插入数据异常"),
  5.     DAO_SELECT_ERROR(false, 100001, "查询数据异常"),
  6.     DAO_UPDATE_ERROR(false, 100002, "更新数据异常"),
  7.     DAO_DELETE_ERROR(false, 100003, "删除数据异常"),
  8.     NULL_POINT(false, 100004, "空指针异常"),
  9.     INDEX_OUT_OF_BOUNDS(false, 100005, "下标越界异常"),
  10.     REQUEST_TIMEOUT(false, 100006, "请求超时"),
  11.     PARAM_ERROR(false, 100007, "参数错误"),
  12.     NOT_INIT_DATA(false, 100008, "数据未初始化"),
  13.     CUSTOM_ERROR(false, 200000, "自定义错误"),
  14.     USER_FORBIDDEN(false, 200001, "用户被禁用"),
  15.     NOT_LOGIN_ERROR(false, 200002, "未登录");
  16.     private Boolean success;
  17.     private Integer code;
  18.     private String message;
  19.     private ResultCodeEnum(boolean success, Integer code, String message) {
  20.         this.success = success;
  21.         this.code = code;
  22.         this.message = message;
  23.     }
  24.     public Boolean getSuccess() {
  25.         return this.success;
  26.     }
  27.     public Integer getCode() {
  28.         return this.code;
  29.     }
  30.     public String getMessage() {
  31.         return this.message;
  32.     }
  33. }
复制代码
3、使用方法

在需要地方代码中使用:throw new UserException()
  1. @Operation(summary = "文件下载")
  2.     @GetMapping("/download")
  3.     public R download(@RequestParam("fileName") String fileName, HttpServletResponse res) {
  4.         // 我这里就演示一下
  5.         if(ObjectUtil.isEmpty(fileName)){
  6.             throw new UserException("文件名不能为空!");
  7.         }
  8.         minioUtil.download(fileName,res);
  9.         return R.success();
  10.     }
复制代码
2.png

4、测试结果

控制台打印:
  1. 2024-09-27T10:12:29.042+08:00 ERROR 20732 --- [eip] [nio-8069-exec-4] c.e.e.c.GlobalExceptionHandlerAdvice     : 全局异常捕获:UserException{code=200000, message=文件名不能为空!}
  2. Disconnected from the target VM, address: '127.0.0.1:62663', transport: 'socket'
复制代码
参数为空,返回前端就会提示定义的消息
  1. {
  2.   "success": false,
  3.   "code": 200000,
  4.   "message": "文件名不能为空!",
  5.   "data": null,
  6.   "dataList": null,
  7.   "total": 0
  8. }
复制代码
最后文章有啥不对,欢迎大佬在评论区指点!!!
如果感觉对你有帮助就点赞推荐或者关注一下吧!!!
3.gif
****

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册