一定义ClobalException
package com.bj66nao.prod.center.bff.admin.exception;
import cn.hutool.core.collection.CollUtil;
import com.bj66nao.prod.center.common.base.error.BusinessException;
import com.bj66nao.prod.center.common.base.error.DubboRpcError;
import com.bj66nao.prod.center.common.base.error.ErrorCode;
import com.bj66nao.prod.center.common.base.util.TraceIdHolder;
import com.bj66nao.prod.center.common.base.web.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
/**
* @Author:Super
* @Date: 2021/11/01
* @Desc: 统一异常处理
*/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 地址解析URL不存在异常处理
* @param request
* @param response
* @param ex
* @return
*/
@ExceptionHandler(value = {NoHandlerFoundException.class})
@ResponseBody
public ApiResult noHandlerFoundException(HttpServletRequest request, HttpServletResponse response, Exception ex) {
ApiResult result = buildApiResult(ErrorCode.HTTP_URL_NO_HANDLER_ERROR);
printErrorLog(request, ex);
return result;
}
/**
* 通用异常处理
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ApiResult handleException(HttpServletRequest request, HttpServletResponse response, Exception ex) {
ApiResult result = buildApiResult(ErrorCode.SYSTEM_ERROR);
printErrorLog(request, ex);
return result;
}
/**
* 业务异常处理
*/
@ExceptionHandler(value = BusinessException.class)
@ResponseBody
public ApiResult handleBusinessException(HttpServletRequest request, HttpServletResponse response, BusinessException ex) {
ApiResult result = buildApiResult(ex.getCode(), ex.getMessage());
printErrorLog(request, ex);
return result;
}
/**
* dubbo-rpc业务异常处理
*/
@ExceptionHandler(value = DubboRpcError.class)
@ResponseBody
public ApiResult handleDubboRpcException(HttpServletRequest request, HttpServletResponse response, DubboRpcError ex) {
ApiResult result = buildApiResult(ex.getCode(), ex.getMessage());
printErrorLog(request, ex);
return result;
}
/**
* 参数异常处理
*/
@ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class})
@ResponseBody
public ApiResult handleBindException(HttpServletRequest request, HttpServletResponse response, BindException ex) {
ApiResult result = buildApiResult(ErrorCode.PARAM_INVALID_ERROR);
printErrorLog(request, ex);
// 获取异常信息
BindingResult exceptions = ex.getBindingResult();
// 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
if (exceptions.hasErrors()) {
List<ObjectError> errors = exceptions.getAllErrors();
if (!errors.isEmpty()) {
// 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
FieldError fieldError = (FieldError) errors.get(0);
return buildApiResult(ErrorCode.PARAM_INVALID_ERROR.code, fieldError.getDefaultMessage());
}
}
return result;
}
/**
* get方法 单独参数校验异常
*/
@ExceptionHandler(value = ConstraintViolationException.class)
@ResponseBody
public ApiResult handleConstraintViolationException(HttpServletRequest request, HttpServletResponse response, ConstraintViolationException ex) {
ApiResult result = buildApiResult(ErrorCode.PARAM_INVALID_ERROR);
printErrorLog(request, ex);
Set<ConstraintViolation<?>> validationSet = ex.getConstraintViolations();
if (CollUtil.isNotEmpty(validationSet)) {
for (ConstraintViolation constraintViolation : validationSet) {
return buildApiResult(ErrorCode.PARAM_INVALID_ERROR.code, constraintViolation.getMessage());
}
}
return result;
}
/**
* 参数缺失异常处理
*/
@ExceptionHandler(value = MissingServletRequestParameterException.class)
@ResponseBody
public ApiResult handleMissingServletRequestParameterException(HttpServletRequest request, HttpServletResponse response, MissingServletRequestParameterException ex) {
ApiResult result = buildApiResult(ErrorCode.PARAM_INVALID_ERROR);
printErrorLog(request, ex);
return result;
}
/**
* 方法不支持异常处理
*/
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
@ResponseBody
public ApiResult handleMethodNotSupportException(HttpServletRequest request, HttpServletResponse response, HttpRequestMethodNotSupportedException ex) {
ApiResult result = buildApiResult(ErrorCode.HTTP_METHOD_NOT_SUPPORT_ERROR.code, ex.getMessage());
printErrorLog(request, ex);
return result;
}
/**
* 请求体为空异常处理
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseBody
public ApiResult handleHttpMessageNotReadableException(HttpServletRequest request, HttpServletResponse response, HttpRequestMethodNotSupportedException ex) {
ApiResult result = buildApiResult(ErrorCode.HTTP_MESSAGE_NOT_READABLE_ERROR);
printErrorLog(request, ex);
return result;
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public ApiResult handleIllegalArgumentExceptionHandler(HttpServletRequest request, IllegalArgumentException e) {
ApiResult result = buildApiResult(ErrorCode.PARAM_INVALID_ERROR.code, e.getMessage());
printErrorLog(request, e);
return result;
}
public ApiResult buildApiResult(Integer code, String message) {
return new ApiResult(code, message, TraceIdHolder.get());
}
public ApiResult buildApiResult(ErrorCode errorCode) {
return buildApiResult(errorCode.code, errorCode.message);
}
public void printErrorLog(HttpServletRequest request, Exception ex) {
log.error("url:{}", request.getRequestURI(), ex);
}
}
二定义DubboRpcError
定义的异常全部继承RuntimeException
都属于运行时异常,属于在调用Dubbo服务的时候,Dubbo抛出的异常(Dubbo服务提供的一次)
public class DubboRpcError extends RuntimeException {
private int code = -1;
private String message;
private String traceId;
public int getCode() {
return this.code;
}
public String getMessage() {
return this.message;
}
public String getTraceId() {
return this.traceId;
}
public void setCode(int code) {
this.code = code;
}
public void setMessage(String message) {
this.message = message;
}
public void setTraceId(String traceId) {
this.traceId = traceId;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof DubboRpcError)) {
return false;
} else {
DubboRpcError other = (DubboRpcError)o;
if (!other.canEqual(this)) {
return false;
} else if (this.getCode() != other.getCode()) {
return false;
} else {
Object this$message = this.getMessage();
Object other$message = other.getMessage();
if (this$message == null) {
if (other$message != null) {
return false;
}
} else if (!this$message.equals(other$message)) {
return false;
}
Object this$traceId = this.getTraceId();
Object other$traceId = other.getTraceId();
if (this$traceId == null) {
if (other$traceId != null) {
return false;
}
} else if (!this$traceId.equals(other$traceId)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof DubboRpcError;
}
public int hashCode() {
int PRIME = true;
int result = 1;
int result = result * 59 + this.getCode();
Object $message = this.getMessage();
result = result * 59 + ($message == null ? 43 : $message.hashCode());
Object $traceId = this.getTraceId();
result = result * 59 + ($traceId == null ? 43 : $traceId.hashCode());
return result;
}
public String toString() {
return "DubboRpcError(code=" + this.getCode() + ", message=" + this.getMessage() + ", traceId=" + this.getTraceId() + ")";
}
public DubboRpcError() {
}
三业务异常处理
public class ErrorCode {
public final Integer code;
public final String message;
public static final ErrorCode SUCCESS = new ErrorCode(0, "执行成功");
public static final ErrorCode SYSTEM_ERROR = new ErrorCode(5000, "系统错误,请稍后重试!");
public static final ErrorCode PARAM_INVALID_ERROR = new ErrorCode(4000, "请求参数非法!");
public static final ErrorCode HTTP_METHOD_NOT_SUPPORT_ERROR = new ErrorCode(4001, "请求方法不支持");
public static final ErrorCode HTTP_MESSAGE_NOT_READABLE_ERROR = new ErrorCode(4002, "请求体错误");
public static final ErrorCode HTTP_URL_NO_HANDLER_ERROR = new ErrorCode(4003, "是什么让你迷失了自己,走错了方向,误入了歧途,退一步海阔天空,回头是岸!!!");
public static final ErrorCode USER_FORBIDDEN_ERROR = new ErrorCode(4010, "用户无权限!!!");
public static ErrorCode fail(Integer code, String message) {
return new ErrorCode(code, message);
}
public ErrorCode formatMessage(Object... args) {
return new ErrorCode(this.code, MessageFormat.format(this.message, args));
}
public ErrorCode copy() {
return new ErrorCode(this.code, this.message);
}
public ErrorCode(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return this.code;
}
public String getMessage() {
return this.message;
}
}
public class BusinessException extends RuntimeException {
private ErrorCode errorCode;
private Object data;
public BusinessException(ErrorCode errorCode) {
super(errorCode.message);
this.errorCode = errorCode.copy();
}
public BusinessException(Integer code, String message) {
super(message);
this.errorCode = new ErrorCode(code, message);
}
public BusinessException(Integer code) {
super("");
this.errorCode = new ErrorCode(code, "");
}
public Integer getCode() {
return this.errorCode.code;
}
public ErrorCode getErrorCode() {
return this.errorCode;
}
public Object getData() {
return this.data;
}
public void setErrorCode(ErrorCode errorCode) {
this.errorCode = errorCode;
}
public void setData(Object data) {
this.data = data;
}