在我们实际项目开放中经常需要我们处理很多的异常,如何在spring boot 项目里面实现全局异常呢?今天我们就来聊聊。
@RestControllerAdvice 和 @ExceptionHandler
@RestControllerAdvice
@RestControllerAdvice是@ControllerAdvice的派生注解,它继承了@ResponseBody,说明了它是一个@Controller的增强器,并且会把信息通过response body响应给前端。
我们可以通过它来拦截spring 的全局异常,例:
@RestControllerAdvice(annotations = {RestController.class, Service.class, Component.class})
通过上面的代码,我们可以看出它会拦截 含有 @RestController,@Service,@Component这些注解类的异常,说白了定义@RestControllerAdvice的类就是一个控制器,可以去拦截符合要求类的异常。
@ExceptionHandler
@ExceptionHandler 作用是拦截和处理具体的某个异常
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@NoArgsConstructor
public class ValidateException extends RuntimeException {
private static final long serialVersionUID = 8641717992917473974L;
private int errorCode;
private String errorMag;
public ValidateException(int errorCode, String errorMag) {
super(errorMag);
this.errorCode = errorCode;
this.errorMag = errorMag;
}
}
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
@Setter
@Getter
@NoArgsConstructor
public class ErrorFormatable {
private int errorCode;
private String errorMsg;
public ErrorFormatable(int errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public ValidateException baseException(String errorMsg) {
return new ValidateException(this.errorCode, String.format(this.errorMsg, errorMsg));
}
public void isEmptyThrow(Object o, String msg) {
if (o == null) {
throw baseException(msg);
}
}
public void isNotEmptyThrow(Object o, String msg) {
if (o != null) {
throw baseException(msg);
}
}
public void isEmptyThrow(Long o, String msg) {
if (o == null || o == 0L) {
throw baseException(msg);
}
}
public void isNotEmptyThrow(Long o, String msg) {
if (o != null && o != 0L) {
throw baseException(msg);
}
}
public void isNotEmptyThrow(Collection collection, String msg) {
if (!CollectionUtils.isEmpty(collection)) {
throw baseException(msg);
}
}
public void isEmptyThrow(Collection collection, String msg) {
if (CollectionUtils.isEmpty(collection)) {
throw baseException(msg);
}
}
public void isEmptyThrow(Integer o, String msg) {
if (o == null || o == 0) {
throw baseException(msg);
}
}
public void isNotEmptyThrow(Integer o, String msg) {
if (o != null && o != 0) {
throw baseException(msg);
}
}
public void isEmptyThrow(String o, String msg) {
if (StringUtils.isBlank(o)) {
throw baseException(msg);
}
}
public void isNotEmptyThrow(String o, String msg) {
if (StringUtils.isNotBlank(o)) {
throw baseException(msg);
}
}
public void assemble(Boolean throwable, String msg) {
if (throwable) {
throw baseException(msg);
}
}
public static final int SUCCESS_CODE = 1000;
public static final String SUCCESS_MSG = "操作成功";
public static final ErrorFormatable NOT_EMPTY = new ErrorFormatable(1001, "%s不能为空");
public static final ErrorFormatable NEED_EMPTY = new ErrorFormatable(1002, "%s必须为空");
public static final ErrorFormatable NOT_EXIST = new ErrorFormatable(1010, "%s不存在");
public static final ErrorFormatable EXIST = new ErrorFormatable(1004, "%s已经存在");
public static final ErrorFormatable CUSTOM = new ErrorFormatable(1005, "%s");
public static final ErrorFormatable INTERNAL_ERROR = new ErrorFormatable(1009, "%s");
public static final int VALIDATE_FAIL_CODE = 1007;
public static final int INTERVAL_FAIL_CODE = 1006;
public static final int AUTHORIZATION_FAIL_CODE = 1008;
public static final int AUTHENTICATION_FAIL_CODE = 1009;
}
import com.fasterxml.jackson.annotation.JsonProperty;
import com.flow.errors.ErrorFormatable;
import com.flow.errors.ValidateException;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Setter
@Getter
public class ServerResponse implements Serializable {
private static final long serialVersionUID = 5880424035498593065L;
private int errorCode;
private String errorMsg;
@JsonProperty
public Boolean success() {
return this.errorCode == ErrorFormatable.SUCCESS_CODE;
}
public ServerResponse(){
this(ErrorFormatable.SUCCESS_CODE, ErrorFormatable.SUCCESS_MSG);
}
public ServerResponse(int errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public ServerResponse(ValidateException e) {
this.errorCode = e.getErrorCode();
this.errorMsg = e.getErrorMag();
}
public ServerResponse(String errorMsg) {
this(ErrorFormatable.SUCCESS_CODE, errorMsg);
}
}
3.4 定义拦截异常类
import com.flow.errors.ErrorFormatable;
import com.flow.errors.ValidateException;
import com.flow.responses.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.io.IOException;
@RestControllerAdvice(annotations = {RestController.class, Service.class, Component.class})
@Slf4j
public class ResponseHandler {
@ExceptionHandler(value = RuntimeException.class)
public ServerResponse runTime(RuntimeException e) {
log.error("运行时异常", e);
return new ServerResponse(ErrorFormatable.INTERVAL_FAIL_CODE, e.getLocalizedMessage());
}
@ExceptionHandler(value = ValidateException.class)
public ServerResponse validateHandler(ValidateException e) {
log.error("系统异常", e);
return new ServerResponse(e.getErrorCode(), e.getErrorMag());
}
@ExceptionHandler(value = IOException.class)
public ServerResponse ioException(IOException e) {
log.error("系统异常", e);
return new ServerResponse(ErrorFormatable.INTERVAL_FAIL_CODE, e.getLocalizedMessage());
}
}