問題:驗證字段過多,每次都使用參數去接收錯誤提示,再返回給前端,導致代碼大量冗餘
解決:使用@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);
}
}