spring boot 项目常用的几个类设计,方便快速搭建项目错误处理模块。
@Getter
public enum ErrorCodeEnums {
//常见错误
success(200,"success"),
paramsError(400,"参数格式或类型错误"),
unAuthentication(401,"未登录或登录超时"),
unAuthorization(403,"未授权访问"),
notFound(404,"未找到访问资源"),
methodNotAllowed(405,"不允许的方法"),
internalError(500,"系统内部错误"),
//业务错误,定义前端错误4xxx,后端错误 5xxx
businessError(4000,"业务处理通用错误"),
loginError(4001,"用户名或密码错误"),
accountDisabled(4002,"账号已被禁用"),
;
final Integer code;
final String message;
ErrorCodeEnums(Integer code, String message) {
this.code = code;
this.message = message;
}
}
HTTP 状态码统一返回200,然后通过code码来区分错误。国内行情大多数达不到RESTful规范标准,所以退而求其次吧。
@Data
@Builder
public class Result<T> implements Serializable {
/**
* 状态码
*/
int code;
/**
* 成功响应数据
*/
T data;
/**
* 错误内容
*/
String message;
/**
* 成功返回数据
* @param data 数据对象
* @return Result封装
* @param <T> 数据类型
*/
public static <T> Result<T> success(T data){
return Result.<T>builder().code(200).message("success").data(data).build();
}
/**
* 无数据返回成功
* @return Result
* @param <T> 数据类型/NULL
*/
public static <T> Result<T> success(){
return Result.success(null);
}
/**
* 失败返回
* @param enums ErrorCodeEnums
* @return Result
* @param <T> 数据类型/Void
*/
public static <T> Result<T> fail(ErrorCodeEnums enums){
return Result.<T>builder().code(enums.getCode()).message(enums.getMessage()).build();
}
/**
* 失败返回
* @param enums ErrorCodeEnums
* @return Result
* @param <T> 数据类型/Void
* @param message 追加详细描述
*/
public static <T> Result<T> fail(ErrorCodeEnums enums,String message){
if (StrUtil.isNotEmpty(message)){
return Result.<T>builder().code(enums.getCode()).message(enums.getMessage()+"-"+message).build();
}else {
return Result.<T>builder().code(enums.getCode()).message(enums.getMessage()).build();
}
}
}
@EqualsAndHashCode(callSuper = true)
@Data
public class BusinessException extends RuntimeException{
ErrorCodeEnums errorCode = ErrorCodeEnums.businessError;
public BusinessException(ErrorCodeEnums errorCode) {
this.errorCode = errorCode;
}
public BusinessException(ErrorCodeEnums errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
业务异常配合ErrorCodeEnums枚举使用,全局错误码靠枚举统一维护。
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({BindException.class,MethodArgumentNotValidException.class})
public Object methodArgumentNotValidException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
List<FieldError> fieldErrors= new ArrayList<>();
if (e instanceof BindException){
fieldErrors=((BindException) e).getFieldErrors();
}
List<String> errorMsg = new ArrayList<>();
for (FieldError error : fieldErrors) {
errorMsg.add("["+error.getField()+"]"+error.getDefaultMessage());
}
String errMsg = String.join(",", errorMsg);
log.error("请求地址:{},参数校验错误 :{}",request.getRequestURI(),errMsg);
return handlerView(Result.fail(ErrorCodeEnums.paramsError, errMsg),request,response);
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public Object MethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e,HttpServletRequest request,HttpServletResponse response) throws IOException {
log.error("请求地址:{},参数格式或类型错误:{}",request.getRequestURI(),e.getMessage(),e);
return handlerView(Result.fail(ErrorCodeEnums.paramsError,"参数格式或类型错误"),request,response);
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public Object httpMessageNotReadableException(HttpMessageNotReadableException e,HttpServletRequest request,HttpServletResponse response) throws IOException {
log.error("请求地址:{},参数格式错误:{}",request.getRequestURI(),e.getMessage());
return handlerView(Result.fail(ErrorCodeEnums.paramsError),request,response);
}
@ExceptionHandler(MissingServletRequestParameterException.class)
public Object missingServletRequestParameterException(MissingServletRequestParameterException e,HttpServletRequest request,HttpServletResponse response) throws IOException {
log.error("请求地址:{},参数缺失:{}",request.getRequestURI(),e.getParameterName());
return handlerView(Result.fail(ErrorCodeEnums.paramsError,e.getParameterName()),request,response);
}
@ExceptionHandler(ConstraintViolationException.class)
public Object constraintViolationException(ConstraintViolationException e,HttpServletRequest request,HttpServletResponse response)throws IOException{
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
List<String> messageList=new ArrayList<>();
for (ConstraintViolation<?> next : constraintViolations) {
messageList.add(next.getMessage());
}
log.error("请求地址:{},参数缺失-:{}",request.getRequestURI(),String.join(",",messageList));
return handlerView(Result.fail(ErrorCodeEnums.paramsError,String.join(",",messageList)),request,response);
}
@ExceptionHandler({AuthenticationException.class})
public Object authenticationException(AuthenticationException authenticationException,HttpServletRequest request,HttpServletResponse response) throws IOException {
log.error("请求地址:{},未登录或令牌无效:{}",request.getRequestURI(),authenticationException.getMessage(),authenticationException);
return handlerView(Result.fail(ErrorCodeEnums.unAuthentication,authenticationException.getMessage()),request,response);
}
@ExceptionHandler({AccessDeniedException.class})
public Object accessDeniedException(AccessDeniedException e,HttpServletRequest request,HttpServletResponse response) throws IOException {
log.error("请求地址:{},未授权访问:{}",request.getRequestURI(),e.getMessage(),e);
return handlerView(Result.fail(ErrorCodeEnums.unAuthorization),request,response);
}
@ExceptionHandler(BusinessException.class)
public Object businessException(BusinessException ex,HttpServletRequest request,HttpServletResponse response) throws IOException {
StackTraceElement traceElement = ex.getStackTrace()[0];
String message;
if (Objects.nonNull(ex.getCause())){
message=ex.getCause().getMessage();
}else{
if (StrUtil.isNotBlank(ex.getMessage())){
message=ex.getMessage();
}else{
message="无错误内容显示或空指针";
}
}
log.error("[BusinessException] {} \n 报错定位:{}",message,traceElement.getClassName()+"."+traceElement.getMethodName()+": 行数:"+traceElement.getLineNumber());
return handlerView(Result.fail(ex.getErrorCode(),ex.getMessage()),request,response);
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Object httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e,HttpServletRequest request,HttpServletResponse response) throws IOException {
String method = e.getMethod();
String uri = request.getRequestURI();
log.error("请求地址:{},method:{} 方法不支持",uri,method);
return handlerView(Result.fail(ErrorCodeEnums.methodNotAllowed),request,response);
}
@ExceptionHandler(NoResourceFoundException.class)
public Object exception(NoResourceFoundException e, HttpServletRequest request, HttpServletResponse response) throws IOException {
log.error("Handler-->"+e.getMessage(), e);
return handlerView(Result.fail(ErrorCodeEnums.notFound),request,response);
}
@ExceptionHandler(Exception.class)
public Object exception(Exception e,HttpServletRequest request,HttpServletResponse response) throws IOException {
log.error("Handler-->"+e.getMessage(), e);
return handlerView(Result.fail(ErrorCodeEnums.internalError),request,response);
}
public Object handlerView(Result<?> result, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (isApi(request)){
response.addHeader("Content-Type","application/json;charset=utf-8");
response.getWriter().write(JSON.toJSONString(result));
return null;
}else{
return result;
}
}
public static boolean isApi(HttpServletRequest request) {
//请求头判断
String header = request.getHeader("X-Request-With");
if ("XMLHttpRequest".equalsIgnoreCase(header)) {
return true;
}
//路径判断
String requestURI = request.getRequestURI();
return requestURI.startsWith("/api/");
}
}
提示:如果仅有接口则直接使用@RestControllerAdvice
注解
https://www.leftso.com/article/2408271229249672.html