(1)定义 @EnableGlobalExceptionHandler 注解,用来控制是否启用全局异常捕获处理
/**
* @author chenyusheng
* @create 2023/6/28 9:56
* @description 是否启用全局异常捕获处理
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableGlobalExceptionHandler {
}
(2)自定义 ServiceException 异常类
/**
* @author chenyusheng
* @create 2023/6/28 9:56
* @description 自定义异常类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(value = JsonInclude.Include.NON_EMPTY)
public class ServiceException extends RuntimeException {
private static final long serialVersionUID = 4224174066989416792L;
private final Integer code;
private Object data;
/**
* 自定义 code+message+data 异常
*
* @param code
* @param message
*/
public ServiceException(Integer code, String message, Object data) {
// 使用父类的 message 字段
super(message);
// 设置错误码
this.code = code;
// 设置额外内容
this.data = data;
}
/**
* 自定义 code+message 异常
*
* @param code
* @param message
*/
public ServiceException(Integer code, String message) {
this(code, message, null);
}
/**
* ServiceExceptionEnum 通用枚举异常,使用自定义 message
*
* @param statusCode
* @param message
*/
public ServiceException(StatusCode statusCode, String message) {
this(statusCode.getCode(), message);
}
/**
* ServiceExceptionEnum 通用枚举异常,使用自定义 message, data
*
* @param statusCode
* @param message
* @param data
*/
public ServiceException(StatusCode statusCode, String message, Object data) {
this(statusCode.getCode(), message, data);
}
/**
* ServiceExceptionEnum 通用枚举异常,使用默认 message
*
* @param statusCode
*/
public ServiceException(StatusCode statusCode) {
this(statusCode.getCode(), statusCode.getMessage());
}
}
/**
* @author chenyusheng
* @create 2023/6/28 9:56
* @description 服务状态码 接口
*/
public interface StatusCode {
/**
* 获取业务码
*
* @return 业务码
*/
Integer getCode();
/**
* 获取业务描述
*
* @return 业务描述
*/
String getMessage();
}
/**
* @author chenyusheng
* @create 2023/6/28 9:56
* @description 自定义服务状态码枚举,这里仅提供一些基于 HttpStatus 状态码的提示;针对具体应用可以通过实现 StatusCode 接口,自定义一套系统状态码提示。
*/
public enum StatusCodeEnum implements StatusCode {
/**
* 200:执行成功
*/
OK(HttpStatus.OK.value(), "执行成功"),
/**
* 400:客户端请求语法错误
*/
BAD_REQUEST(HttpStatus.BAD_REQUEST.value(), "客户端请求语法错误"),
/**
* 401:认证失败
*/
UNAUTHORIZED(HttpStatus.UNAUTHORIZED.value(), "认证失败"),
/**
* 403:权限不足
*/
FORBIDDEN(HttpStatus.FORBIDDEN.value(), "权限不足"),
/**
* 404:请求资源不存在
*/
NOT_FOUND(HttpStatus.NOT_FOUND.value(), "请求资源不存在"),
/**
* 500:服务器内部错误
*/
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器内部错误"),
/**
* 502:网关异常
*/
BAD_GATEWAY(HttpStatus.BAD_GATEWAY.value(), "网关异常"),
/**
* 503:服务器当前无法处理请求
*/
SERVICE_UNAVAILABLE(HttpStatus.SERVICE_UNAVAILABLE.value(), "服务器当前无法处理请求"),
/**
* 429:请求太多,达到限制
*/
TOO_MANY_REQUESTS(HttpStatus.TOO_MANY_REQUESTS.value(), "请求太多,达到限制");
/**
* 异常码
*/
private final Integer code;
/**
* 异常消息
*/
private final String message;
StatusCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
/**
* 获取业务码
*
* @return 业务码
*/
@Override
public Integer getCode() {
return code;
}
/**
* 获取业务描述
*
* @return 业务描述
*/
@Override
public String getMessage() {
return message;
}
}
(3)定义 CommonResult<T> 通用结果包装类
/**
* @param <T>
* @author chenyusheng
* @create 2023/6/28 9:56
* @description 通用结果包装类
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel("公共接口返回包装类")
public class CommonResult<T> {
public static final Integer CODE_SUCCESS = StatusCodeEnum.OK.getCode();
/**
* 状态码
*/
@ApiModelProperty("状态码")
private Integer code;
/**
* 消息提示
*/
@ApiModelProperty("消息提示")
private String message;
/**
* 返回数据
*/
@ApiModelProperty("返回数据")
private T data;
/**
* 失败
*
* @param code 状态码
* @param message 消息提示
*/
public static <T> CommonResult<T> error(Integer code, String message) {
return CommonResult.error(code, message, null);
}
/**
* 失败
*
* @param code 状态码
* @param message 消息提示
* @param data 返回数据
* @param <T>
*/
public static <T> CommonResult<T> error(Integer code, String message, T data) {
return CommonResult.<T>builder()
.code(code)
.message(StringUtils.isNotBlank(message) ? message : "执行异常")
.data(data)
.build();
}
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> CommonResult<T> success(T data) {
return CommonResult.success("执行成功!", data);
}
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> CommonResult<T> success(String message, T data) {
return CommonResult.success(CODE_SUCCESS, message, data);
}
/**
* 成功
*
* @param code
* @param message
* @param data
* @param <T>
* @return
*/
public static <T> CommonResult<T> success(Integer code, String message, T data) {
return CommonResult.<T>builder()
.code(code)
.message(StringUtils.isNotBlank(message) ? message : "执行成功")
.data(data)
.build();
}
}
(4)自定义GlobalExceptionHandler 全局异常处理类
/**
* @author chenyusheng
* @create 2023/6/28 9:56
* @description 全局异常处理
*/
@Slf4j
@RestControllerAdvice(annotations = {EnableGlobalExceptionHandler.class})
@SuppressWarnings("all")
public class GlobalExceptionHandler {
/**
* 处理 ServiceException 自定义异常
*
* @param req HttpServletRequest
* @param ex ServiceException
* @return CommonResult
*/
@ExceptionHandler(value = ServiceException.class)
public CommonResult serviceExceptionHandler(HttpServletRequest req, ServiceException ex) {
log.debug("ServiceException自定义异常:", ex);
return CommonResult.error(ex.getCode(), ex.getMessage(), ex.getData());
}
/**
* 处理 MissingServletRequestParameterException 异常
*
* @param req HttpServletRequest
* @param ex MissingServletRequestParameterException
* @return CommonResult
*/
@ExceptionHandler(value = MissingServletRequestParameterException.class)
public CommonResult missingServletRequestParameterExceptionHandler(HttpServletRequest req, MissingServletRequestParameterException ex) {
log.error("缺少请求参数异常:", ex);
return CommonResult.error(StatusCodeEnum.BAD_REQUEST.getCode(), ex.getMessage());
}
/**
* 处理其它 MethodArgumentNotValidException 参数校验异常
*
* @param req HttpServletRequest
* @param ex MethodArgumentNotValidException
* @return
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public CommonResult methodArgumentNotValidExceptionHandler(HttpServletRequest req, MethodArgumentNotValidException ex) {
log.error("方法参数无效异常:", ex);
return CommonResult.error(StatusCodeEnum.BAD_REQUEST.getCode(), Objects.requireNonNull(ex.getBindingResult().getFieldError()).getField() + " : " + ex.getBindingResult().getFieldError().getDefaultMessage());
}
/**
* 处理其它 Exception 异常
*
* @param req HttpServletRequest
* @param ex Exception
* @return
*/
@ExceptionHandler(value = Exception.class)
public CommonResult exceptionHandler(HttpServletRequest req, Exception ex) {
log.error("Exception异常:", ex);
return CommonResult.error(StatusCodeEnum.INTERNAL_SERVER_ERROR.getCode(), ex.getMessage());
}
}
(5)在主程序使用 @EnableGlobalExceptionHandler 显示启动即可;