【數據校驗】統一錯誤返回

問題:驗證字段過多,每次都使用參數去接收錯誤提示,再返回給前端,導致代碼大量冗餘

解決:使用@ControllerAdvice 註解做統一的異常處理,對所有驗證錯誤進行捕獲,統一返回給前端

import com.google.common.collect.Lists;
import com.pilot.oms.service.common.constant.ResultType;
import com.pilot.oms.service.common.entity.basic.ResponsePageResult;
import com.pilot.oms.service.common.entity.basic.ResponseResult;
import com.pilot.oms.service.common.exception.ReturnPageValuesRuntimeException;
import com.pilot.oms.service.common.exception.ReturnValuesRuntimeException;
import com.pilot.oms.service.common.exception.UnauthorizedRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
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.bind.annotation.ResponseStatus;

import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Controller統一異常處理
 * @author : zhouww
 */
@ControllerAdvice
public class AllControllerAdvice {
    private static Logger logger = LoggerFactory.getLogger(AllControllerAdvice.class);

    /**
     * 全局異常捕捉處理
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResponseResult<?> errorHandler(Exception ex) {
        logger.error("接口出現嚴重異常:{}", ex);
        return new ResponseResult<>(ResultType.SYS_SO_BUSY, "服務異常,請稍後再試!", Lists.newArrayList());
    }

    /**
     * 捕捉UnauthorizedRuntimeException用戶登錄信息獲取失敗異常處理
     *
     * @return
     */
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(UnauthorizedRuntimeException.class)
    @ResponseBody
    public ResponseResult<?> handleUnauthorized(UnauthorizedRuntimeException ex) {
        return new ResponseResult<>(ResultType.USER_NO_AUTH, "加載用戶信息失敗或用戶無權限!", Lists.newArrayList());
    }

    /**
     * 處理@RequestBody請求參數驗證異常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseResult<?> validationErrorHandler(MethodArgumentNotValidException ex) {
        // 同樣是獲取BindingResult對象,然後獲取其中的錯誤信息
        // 如果前面開啓了fail_fast,事實上這裏只會有一個信息
        // 如果沒有,則可能又多個
        List<String> errInfoList = ex.getBindingResult().getAllErrors()
                .stream()
                .map(v -> ((FieldError) v).getField() + " " + v.getDefaultMessage())
                .collect(Collectors.toList());
        return new ResponseResult<>(ResultType.REQUEST_PARA_ERROR, errInfoList.toString(), Lists.newArrayList());
    }

    /**
     * 處理@RequestParam和@PathVariable請求參數驗證異常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResponseResult<?> validationErrorHandler(ConstraintViolationException ex) {
        List<String> errInfoList = ex.getConstraintViolations()
                .stream()
                .map(v -> v.getPropertyPath().toString().substring(v.getPropertyPath().toString().indexOf(".") + 1) + " " + v.getMessage())
                .collect(Collectors.toList());
        return new ResponseResult<>(ResultType.REQUEST_PARA_ERROR, errInfoList.toString(), Lists.newArrayList());
    }

    /**
     * 處理400錯誤,缺少接口要求必填參數
     *
     * @param ex MissingServletRequestParameterException
     * @return ResponseResult
     */
    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseBody
    public ResponseResult<?> requestMissingServletRequest(MissingServletRequestParameterException ex) {
        // System.out.println("400..MissingServletRequest");
        String errMsg = "缺少接口要求必填參數";
        return new ResponseResult<>(ResultType.REQUEST_PARA_ERROR, errMsg, new ArrayList<>());
    }

    /**
     * 處理400錯誤,請求參數無法被讀取
     *
     * @param ex HttpMessageNotReadableException
     * @return ResponseResult
     */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    @ResponseBody
    public ResponseResult<?> requestNotReadable(HttpMessageNotReadableException ex) {
        // System.out.println("400..HttpMessageNotReadable");
        String errMsg = "反序列化失敗,參數格式與當前接口要求不一致";
        return new ResponseResult<>(ResultType.REQUEST_PARA_ERROR, errMsg, new ArrayList<>());
    }

    /**
     * 處理400錯誤,參數類型不匹配
     *
     * @param ex HttpMessageNotReadableException
     * @return ResponseResult
     */
    @ExceptionHandler({TypeMismatchException.class})
    @ResponseBody
    public ResponseResult<?> requestTypeMismatch(TypeMismatchException ex) {
        System.out.println("400..TypeMismatchException");
        String errMsg = "參數類型不匹配";
        return new ResponseResult<>(ResultType.REQUEST_PARA_ERROR, errMsg, new ArrayList<>());
    }

    /**
     * 處理返回通用格式的待返回值的運行時異常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ReturnValuesRuntimeException.class)
    @ResponseBody
    public ResponseResult<?> checkReturnValuesRunctionException(ReturnValuesRuntimeException ex) {
        return new ResponseResult<>(ex.getRetStatus(),ex.getRetCode(),ex.getErrMessage(), Lists.newArrayList());
    }

    /**
     * 處理返回分頁格式的待返回值的運行時異常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ReturnPageValuesRuntimeException.class)
    @ResponseBody
    public ResponsePageResult<?> checkReturnPageValuesRunctionException(ReturnPageValuesRuntimeException ex) {
        ResponsePageResult responsePageResult = new ResponsePageResult();
        responsePageResult.setStatus(ex.getRetStatus());
        responsePageResult.setMsg(ex.getErrMessage());
        responsePageResult.setGlobalPageIndex(0);
        responsePageResult.setGlobalPageSize(0);
        responsePageResult.setTotal(0);
        responsePageResult.setTotalPage(0);
        responsePageResult.setData(Lists.newArrayList());
        return responsePageResult;
    }

}
統一錯誤提示數據結構

import com.pilot.oms.service.common.constant.ResultType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
 * 返回基類
 */
@Data
@ApiModel(value = "ResponseResult", description = "返回對象基類")
public class ResponseResult<T> implements ResponseEntity {

    @ApiModelProperty(value = "返回結果值 0:成功, 1:參數不正確, 2:JSON參數格式錯誤, 3:數據庫操作失敗, 4:用戶未授權, 5:服務器忙, 6:用戶未登錄, 7:其他錯誤, 8:當保存操作時需要進行再次確認", required = true)
    private int status;
    @ApiModelProperty(value = "返回結果Code", required = true)
    private String code;
    @ApiModelProperty(value = "返回結果描述", required = true)
    private String msg;
    @ApiModelProperty(value = "返回結果對象", required = true)
    private List<T> data;

    public ResponseResult() {
    }


    public ResponseResult(ResultType resultType, List<T> data) {
        this.status = resultType.getValue();
        this.code = resultType.getCode();
        this.msg = resultType.getDesc();
        this.data = data;
    }

    public ResponseResult(ResultType resultType, String errMsg, List<T> data) {
        this.status = resultType.getValue();
        this.code = resultType.getCode();
        this.msg = errMsg;
        this.data = data;
    }

    public ResponseResult(int status, String code, String errMsg, List<T> data) {
        this.status = status;
        this.code = code;
        this.msg = errMsg;
        this.data = data;
    }
}

分頁數據返回提示
/**
 * 頁面返回對象基類
 *
 * @param <T>
 * @author licz-Soft
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "ResponsePageResult", description = "分頁返回對象基類")
public class ResponsePageResult<T> extends ResponseResult<T> {
    @ApiModelProperty(value = "當前頁碼", required = true)
    private long globalPageIndex;
    @ApiModelProperty(value = "每頁記錄數", required = true)
    private long globalPageSize;
    @ApiModelProperty(value = "總記錄數", required = true)
    private long total;
    @ApiModelProperty(value = "總頁數", required = true)
    private long totalPage;

    public ResponsePageResult(int status, String code, String msg, List<T> data) {
        super.setStatus(status);
        super.setCode(code);
        super.setMsg(msg);
        super.setData(data);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章