【SpringBoot】面向生产的统一异常处理方式
创始人
2024-05-22 21:56:34
0

文章目录

  • 1.Spring MVC异常统一处理的三种方式
    • @Controller + @ExceptionHandler
    • 实现 HandlerExceptionResolver 接口
    • @ControllerAdvice+@ExceptionHandler
  • 2.统一响应返回
  • 3.统一异常处理

1.Spring MVC异常统一处理的三种方式

  • 使用 @ ExceptionHandler 注解:对当前所在Controller的异常进行处理
  • 实现 HandlerExceptionResolver 接口
  • 使用@controlleradvice+@ ExceptionHandler注解:对全局异常进行处理(推荐)

@Controller + @ExceptionHandler

缺点:进行异常处理的方法必须与出错的方法在同一个Controller里面,不能全局控制异常。每个类都要写一遍:

@Controller
public class GlobalController {/*** 用于处理异常的* @return*/@ExceptionHandler({MyException.class})public String exception(MyException e) {System.out.println(e.getMessage());e.printStackTrace();return "exception";}@RequestMapping("test")public void test() {throw new MyException("出错了!");}
}

实现 HandlerExceptionResolver 接口

可以进行全局的异常控制

@Component
@Slf4j
public class GlobalDefaultExceptionHandler implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {log.info("==============Exception Start 000000=============");if (ex instanceof BaseException) {log.debug(ex, ex);}else {log.error(ex, ex);}log.info("==============Exception End 000000=============");//AJAX请求if (NetworkUtil.isAjax(request)) {String msg = null;String code = null;String detail = null;if (ex instanceof BaseException) {msg = ((BaseException) ex).getErrorMsg();code = ((BaseException) ex).getErrorCode();detail = ((BaseException) ex).getMsgDetail();}else {FSTErrorCode fc = FSTErrorCode.SYS_ERROR_000000;msg = fc.getErrorMsg();code = fc.getErrorCode();detail = fc.getMsgDetail();}try {JSONObject result = new JSONObject();result.put("msg", msg);result.put("code", code);result.put("detail", detail);response.setContentType("text/html;charset=utf-8");response.getWriter().print(result.toString());} catch (IOException e) {e.printStackTrace();}return null;}//非Ajax请求else {ModelAndView mv = new ModelAndView();mv.setViewName("error/error");//跳转到resources/template/error/error.htmlmv.addObject("exception", ex.toString().replaceAll("\n", "
"));return mv;}} }

@ControllerAdvice+@ExceptionHandler

  • 可以实现全局的异常捕获
@ControllerAdvice
@ResponseBody
@Slf4j
public class WebExceptionHandle {private static Logger logger = LoggerFactory.getLogger(WebExceptionHandle.class);/*** 400 - Bad Request*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(HttpMessageNotReadableException.class)public ServiceResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {log.error("参数解析失败", e);return ServiceResponseHandle.failed("could_not_read_json");}/*** 405 - Method Not Allowed*/@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)@ExceptionHandler(HttpRequestMethodNotSupportedException.class)public ServiceResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {log.error("不支持当前请求方法", e);return ServiceResponseHandle.failed("request_method_not_supported");}/*** 415 - Unsupported Media Type*/@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)@ExceptionHandler(HttpMediaTypeNotSupportedException.class)public ServiceResponse handleHttpMediaTypeNotSupportedException(Exception e) {log.error("不支持当前媒体类型", e);return ServiceResponseHandle.failed("content_type_not_supported");}/*** 500 - Internal Server Error*/@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)@ExceptionHandler(Exception.class)public ServiceResponse handleException(Exception e) {if (e instanceof BusinessException){return ServiceResponseHandle.failed("BUSINESS_ERROR", e.getMessage());}log.error("服务运行异常", e);e.printStackTrace();return ServiceResponseHandle.failed("server_error");} 
}

2.统一响应返回

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApiResult implements Serializable {private static final long serialVersionUID = 411731814484355577L;private int code;private String msg;private boolean isSuccess;private T data;public static ApiResult success() {return success("success");}public static  ApiResult success(T data) {return (ApiResult) ApiResult.builder().code(0).msg("操作成功").isSuccess(true).data(data).build();}public static ApiResult fail() {return fail(-1);}public static ApiResult fail(int code) {return fail(code, "fail");}public static ApiResult fail(int code,String message) {return fail(code, message);}public static  ApiResult fail(T data) {return fail(-1, data);}public static  ApiResult fail(int code, T data) {return (ApiResult) ApiResult.builder().code(code).msg("操作失败").isSuccess(false).data(data).build();}public static  ApiResult success(int code, String message, T data) {return (ApiResult) ApiResult.builder().code(code).msg(message).isSuccess(true).data(data).build();}public static  ApiResult fail(int code, String message, T data) {return (ApiResult) ApiResult.builder().code(code).msg(message).isSuccess(false).data(data).build();}@Overridepublic String toString() {return "ApiResult(responseCode=" + this.getCode() + ", responseMsg=" + this.getMsg() + ", isSuccess=" + this.isSuccess() + ", data=" + this.getData() + ")";}
}

3.统一异常处理

  1. 使用@ControllerAdvice+ @ExceptionHandler注解进行异常全局捕获;
  2. 定义一个通用的异常捕获方法,便于捕获未定义的异常信息;
  3. 自定一个异常类,捕获针对项目或业务的异常;

自定义异常

@Data
public class BusinessException extends RuntimeException {private Integer code;public BusinessException(Integer code, String message) {super(message);this.code = code;}public BusinessException(ResultCodeEnum resultCodeEnum) {super(resultCodeEnum.getMessage());this.code = resultCodeEnum.getCode();}@Overridepublic String toString() {return "BusinessException{" + "code=" + code + ", message=" + this.getMessage() + '}';}
}

异常类型统一使用枚举类管理

@Getter
public enum ResultCodeEnum {SUCCESS(true, 20000, "成功"),UNKNOWN_ERROR(false, 20001, "未知错误"),,PARAM_ERROR(false, 20002, "参数错误"),;// 响应是否成功private Boolean success;// 响应状态码private Integer code;// 响应信息private String message;ResultCodeEnum(boolean success, Integer code, String message) {this.success = success;this.code = code;this.message = message;}
}

定义全局异常捕获器

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {/**-------- 通用异常处理方法 --------**/@ExceptionHandler(Exception.class)@ResponseBodypublic ApiResult error(Exception e) {e.printStackTrace();return ApiResult.fail(-1,"通用异常");}/**-------- 指定异常处理方法 --------**/@ExceptionHandler(NullPointerException.class)@ResponseBodypublic ApiResult error(NullPointerException e) {e.printStackTrace();log.error(ExceptionUtil.getMessage(e));return ApiResult.fail(-1,"空指针异常");}@ExceptionHandler(HttpClientErrorException.class)@ResponseBodypublic ApiResult error(IndexOutOfBoundsException e) {e.printStackTrace();log.error(ExceptionUtil.getMessage(e));return ApiResult.fail(-1,"下标越界异常");}/**-------- 自定义定异常处理方法 --------**/@ExceptionHandler(BusinessException.class)@ResponseBodypublic ApiResult error(BusinessException e) {e.printStackTrace();log.error(ExceptionUtil.getMessage(e));return ApiResult.fail(-1,"业务异常");}
}

【转载】Java统一异常处理及架构实战
https://juejin.cn/post/6844904033488994317

https://github.com/purgeteam/unified-dispose-springboot

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...