注解ControllerAdvice 配合 注解ExceptionHandler 实现全局异常返回统一的业务实体

前言

mvc应用开发,基于Json数据的restfull交互接口。所有的正常或者异常的数据返回,都需要定义固定的格式。比如,系统出现异常,也能返回统一的错误码+错误信息,而不是返回一堆乱码给接口调用者。

统一返回的业务实体定义

package com.argrace.platform.dal.dto;

import lombok.Data;

/**
 * @author keyingbo
 */
@Data
public class Result<T> {
     

    public enum ResultCode {
     
        SUCCESS(200, "成功"),
        REQUEST_ERROR(400, "请求错误"),
        REQUEST_AUTH_ERROR(401, "请求认证错误"),
        REQUEST_SIGN_ERROR(402, "请求签名错误"),
        REQUEST_FORBIDDEN(403, "请求被禁止"),
        SERVICE_NOT_FOUND(404, "服务未找到"),
        SERVICE_ERROR(500, "服务端错误"),
        SQL_ERROR(501, "服务端SQL错误"),
        CALL_REMOTE_API_ERROR(2000, "服务端调用API失败"),
        REMOTE_API_ERROR(2001, "远程API失败"),
        PARAMETERS_IS_EMPTY(2002, "参数为空"),
        PARAMETERS_IS_ERROR(2002, "参数错误")
        ;

        private int value;
        private String message;

        ResultCode(int value, String message) {
     
            this.value = value;
            this.message = message;
        }

        public int getValue() {
     
            return value;
        }

        public String getMessage() {
     
            return message;
        }

        public String getMsg() {
     
            return message;
        }

        public static ResultCode parseValue(int value) {
     
            ResultCode[] values = ResultCode.values();
            for (ResultCode resultCode : values) {
     
                if (resultCode.getValue() == value) {
     
                    return resultCode;
                }
            }
            return null;
        }
    }

    private int code = 200;
    private String message;
    private T data;

    public Result() {
     
    }

    public Result(T data) {
     
        this.code = ResultCode.SUCCESS.getValue();
        this.message = ResultCode.SUCCESS.getMessage();
        this.data = data;
    }

    public Result(int code, String message) {
     
        this.code = code;
        this.message = message;
    }

    public static Result ok() {
     
        return new Result<>(null);
    }

    public static <T> Result<T> ok(T data) {
     
        return new Result<>(data);
    }


    public static <T> Result<T> error(ResultCode resultCode) {
     
        return new Result<>(resultCode.value, resultCode.message);
    }

    public static <T> Result<T> withErr(ResultCode resultCode, String msg) {
     
        return new Result<T>(resultCode.value, msg);
    }

    public static <T> Result<T> withErr(ResultCode resultCode) {
     
        return new Result<T>(resultCode.value, resultCode.getMessage());
    }

    public static <T> Result<T> error(ResultCode resultCode, String message) {
     
        return new Result<>(resultCode.value,  message);
    }

    public static <T> Result<T> error(int code, String message) {
     
        return new Result<>(code, message);
    }

    public static boolean isOk(Result result) {
     
        return ResultCode.SUCCESS.getValue() == result.code;
    }
}

统一异常处理类GlobalExceptionHandler

package com.argrace.platform.interceptor;

import com.argrace.platform.dal.dto.Result;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class GlobalExceptionHandler {
     
   private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

   @ExceptionHandler({
     ConstraintViolationException.class})
   @ResponseBody
   public <T> Result<T> resolveConstraintViolationException(ConstraintViolationException ex) {
     
      Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
      String msg;
      if (!CollectionUtils.isEmpty(constraintViolations)) {
     
         StringBuilder msgBuilder = new StringBuilder();
         Iterator var5 = constraintViolations.iterator();

         while(var5.hasNext()) {
     
            ConstraintViolation constraintViolation = (ConstraintViolation)var5.next();
            msgBuilder.append(constraintViolation.getMessage()).append(",");
         }

         String errorMessage = msgBuilder.toString();
         if (errorMessage.length() > 1) {
     
            errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
         }

         msg = errorMessage;
      } else {
     
         msg = ex.getMessage();
      }

      this.logger.info("bean参数检验不通过:{}", msg);
      return Result.withErr(Result.ResultCode.PARAMETERS_IS_ERROR, msg);
   }

   @ExceptionHandler({
     MethodArgumentNotValidException.class})
   @ResponseBody
   public <T> Result<T> resolveMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
     
      List<ObjectError> objectErrors = ex.getBindingResult().getAllErrors();
      String msg;
      if (!CollectionUtils.isEmpty(objectErrors)) {
     
         StringBuilder msgBuilder = new StringBuilder();
         Iterator var5 = objectErrors.iterator();

         while(var5.hasNext()) {
     
            ObjectError objectError = (ObjectError)var5.next();
            msgBuilder.append(objectError.getDefaultMessage()).append(",");
         }

         String errorMessage = msgBuilder.toString();
         if (errorMessage.length() > 1) {
     
            errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
         }

         msg = errorMessage;
      } else {
     
         msg = ex.getMessage();
      }

      this.logger.info("method参数检验不通过:{}", msg);
      return Result.withErr(Result.ResultCode.PARAMETERS_IS_ERROR, msg);
   }

   @ExceptionHandler({
     BindException.class})
   @ResponseBody
   public <T> Result<T> bindException(BindException ex) {
     
      List<ObjectError> objectErrors = ex.getBindingResult().getAllErrors();
      String msg;
      if (!CollectionUtils.isEmpty(objectErrors)) {
     
         StringBuilder msgBuilder = new StringBuilder();
         Iterator var5 = objectErrors.iterator();

         while(var5.hasNext()) {
     
            ObjectError objectError = (ObjectError)var5.next();
            msgBuilder.append(objectError.getDefaultMessage()).append(",");
         }

         String errorMessage = msgBuilder.toString();
         if (errorMessage.length() > 1) {
     
            errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
         }

         msg = errorMessage;
      } else {
     
         msg = ex.getMessage();
      }

      this.logger.info("BindException参数检验不通过:{}", msg);
      return Result.withErr(Result.ResultCode.PARAMETERS_IS_ERROR, msg);
   }

   @ExceptionHandler({
     SQLException.class})
   @ResponseBody
   public <T> Result<T> handlerSQLException(SQLException ex) {
     
      this.logger.error("SQL异常:result={}", ex.getMessage());
      return Result.withErr(Result.ResultCode.SERVICE_ERROR, ex.getMessage());
   }

   @ExceptionHandler({
     HttpRequestMethodNotSupportedException.class})
   @ResponseBody
   public <T> Result<T> handlerHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) {
     
      this.logger.error("HttpRequestMethodNotSupportedException:result=", ex);
      return Result.withErr(Result.ResultCode.SERVICE_ERROR, ex.getMessage());
   }

   @ExceptionHandler({
     RuntimeException.class})
   @ResponseBody
   public <T> Result<T> handlerRuntimeException(RuntimeException ex) {
     
      this.logger.error("RuntimeException:result=", ex);
      return Result.withErr(Result.ResultCode.SERVICE_ERROR, ex.getMessage());
   }

   @ExceptionHandler({
     Exception.class})
   @ResponseBody
   public <T> Result<T> handlerException(Exception ex) {
     
      this.logger.error("Exception异常:result=", ex);
      return Result.withErr(Result.ResultCode.SERVICE_ERROR);
   }
}

你可能感兴趣的:(springboot)