问题:验证字段过多,每次都使用参数去接收错误提示,再返回给前端,导致代码大量冗余
解决:使用@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;
@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());
}
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(UnauthorizedRuntimeException.class)
@ResponseBody
public ResponseResult<?> handleUnauthorized(UnauthorizedRuntimeException ex) {
return new ResponseResult<>(ResultType.USER_NO_AUTH, "加载用户信息失败或用户无权限!", Lists.newArrayList());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseResult<?> validationErrorHandler(MethodArgumentNotValidException ex) {
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());
}
@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());
}
@ExceptionHandler({MissingServletRequestParameterException.class})
@ResponseBody
public ResponseResult<?> requestMissingServletRequest(MissingServletRequestParameterException ex) {
String errMsg = "缺少接口要求必填参数";
return new ResponseResult<>(ResultType.REQUEST_PARA_ERROR, errMsg, new ArrayList<>());
}
@ExceptionHandler({HttpMessageNotReadableException.class})
@ResponseBody
public ResponseResult<?> requestNotReadable(HttpMessageNotReadableException ex) {
String errMsg = "反序列化失败,参数格式与当前接口要求不一致";
return new ResponseResult<>(ResultType.REQUEST_PARA_ERROR, errMsg, new ArrayList<>());
}
@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<>());
}
@ExceptionHandler(ReturnValuesRuntimeException.class)
@ResponseBody
public ResponseResult<?> checkReturnValuesRunctionException(ReturnValuesRuntimeException ex) {
return new ResponseResult<>(ex.getRetStatus(),ex.getRetCode(),ex.getErrMessage(), Lists.newArrayList());
}
@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;
}
}
分页数据返回提示
@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);
}
}