【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

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...