@controlleradvice+@ 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("出错了!");}
}
可以进行全局的异常控制
@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
@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");}
}
@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() + ")";}
}
自定义异常
@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