【数据校验】统一错误返回

问题:验证字段过多,每次都使用参数去接收错误提示,再返回给前端,导致代码大量冗余

解决:使用@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 
 * @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);
    }
}

你可能感兴趣的:(数据校验,java)