参数校验
通过RestControllerAdvice和ExceptionHandler实现全局异常捕获
起因:
我么希望通过全局统一的异常处理将自定义错误码以json的形式发送给前端。
步骤:
1.定义一个统一结果返回类BaseRspVo
import com.shizhongcai.business.common.domain.enums.ErrorCodesEnum;
import com.shizhongcai.business.common.exception.BaseException;
import lombok.Data;
@Data
public class BaseRspVo<T> {
private boolean success;
private String msg;
private Integer errorCode;
private T data;
public BaseRspVo() {
}
public BaseRspVo (T data){
this.success = true;
this.msg= ErrorCodesEnum.SUCCESS.getMsg();
this.errorCode = ErrorCodesEnum.SUCCESS.getCode();
this.data = data;
}
public BaseRspVo (boolean success, String msg, int errorCode) {
this.success = success;
this.msg = msg;
this.errorCode = errorCode;
}
public BaseRspVo (boolean success, String msg, int errorCode, T data) {
this(success,msg,errorCode);
this.data = data;
}
public BaseRspVo(ErrorCodesEnum errorCode) {
if(errorCode == ErrorCodesEnum.SUCCESS) {
this.success = true;
} else {
this.success = false;
}
this.msg = errorCode.getMsg();
this.errorCode = errorCode.getCode();
}
public static BaseRspVo success(Object data){
return new BaseRspVo(data);
}
public static BaseRspVo fail(ErrorCodesEnum errorCode){
return new BaseRspVo(errorCode);
}
public static BaseRspVo fail(BaseException e){
return new BaseRspVo(false,e.getMsg(), ErrorCodesEnum.DEFAULT_FAIL.getCode());
}
public static BaseRspVo fail(int code,String msg){
return new BaseRspVo(false,msg, code);
}
}
2.定义统一错误枚举类,包含错误码及错误原因
public enum ErrorCodesEnum {
SUCCESS(10000,"成功"),
SYS_ERROR(10001,"系统异常,请稍后再试"),
PARAM_ERROR(10002,"参数异常"),
NO_HANDLER_FOUND(10003,"路径不存在,请检查路径是否正确"),
DEFAULT_FAIL(10004,"未知异常,请稍后再试"),
DECRYPT_ERROR(10005,"解密出错"),
REQUEST_TOO_FAST(10006,"您的请求太快啦!请在稍后再试"),
;
/**
* 错误码
*/
private int code;
/**
* 错误描述
*/
private String msg;
ErrorCodesEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
3.定义基础异常类BaseException
接下来我们需要将业务异常都同意封装到这个异常类中
import com.shizhongcai.business.common.domain.enums.ErrorCodesEnum;
import lombok.Data;
@Data
public class BaseException extends Exception{
private int code;
private String msg;
public BaseException(ErrorCodesEnum errorCode){
this.code = errorCode.getCode();
this.msg = errorCode.getMsg();
}
}
4.创建全局异常处理器GlobalExceptionHandler
@ControllerAdvice可以捕获全局异常 @RestControllerAdvice相对于@ControllerAdvice直接返回JSON @ExceptionHandler 对于捕获的异常进行拦截处理,我们可以通过该注解实现自定义异常处理,配置的 value 指定需要拦截的异常类型。
import com.shizhongcai.business.common.domain.vo.BaseRspVo;
import com.shizhongcai.business.common.domain.enums.ErrorCodesEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 基础异常捕获
* @param e
* @return
*/
@ExceptionHandler(BaseException.class)
public BaseRspVo handleTSharkException(BaseException e) {
logger.error("异常信息:{}",e);
return BaseRspVo.fail(e);
}
/**
* 未知异常
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public BaseRspVo handleException(Exception e) {
logger.error("异常信息:{}",e);
return BaseRspVo.fail(ErrorCodesEnum.DEFAULT_FAIL);
}
/**
* 参数校验异常
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public BaseRspVo handleException(MethodArgumentNotValidException e) {
logger.error("请求参数不合法:{}",e.getBindingResult());
//获取所有校验失败项
List<FieldError> errors = e.getBindingResult().getFieldErrors();
//处理异常校验项
Map<String,String> errorMap = new HashMap<>();
if(!CollectionUtils.isEmpty(errors)) {
for (FieldError error : errors) {
errorMap.put(error.getField(),error.getDefaultMessage());
}
}
BaseRspVo baseRspVo = BaseRspVo.fail(ErrorCodesEnum.PARAM_ERROR);
baseRspVo.setData(errorMap);
return baseRspVo;
}
}