1 基本类
1.1 接口IBizError
public interface IBizError {
int getCode();
String getMessage();
}
1.2 异常处理类BizException
import lombok.Data;
import java.io.Serial;
@Data
public class BizException extends RuntimeException {
@Serial
private static final long serialVersionUID = 6577165386030770043L;
/** 错误代码 */
private IBizError bizError;
/** 扩展信息 */
private String extendMessage;
private Throwable cause;
public BizException(IBizError bizError) {
super(String.format("[code=%s, message=%s]", bizError.getCode(), bizError.getMessage()));
this.bizError = bizError;
}
public BizException(IBizError bizError, String extendMessage) {
super(String.format("[code=%s, message=%s, extendMessage=%s]", bizError.getCode(), bizError.getMessage(), extendMessage));
this.bizError = bizError;
this.extendMessage = extendMessage;
}
public BizException(IBizError bizError, Throwable cause) {
super(String.format("[code=%s, message=%s]", bizError.getCode(), bizError.getMessage(), cause));
this.bizError = bizError;
this.cause = cause;
}
}
1.3 业务异常编码基类BizError
public class BizError implements IBizError {
public static final IBizError SUCCESS = new BizError(200, "成功");
public static final IBizError HTTP_201 = new BizError(201, "Accepted");
public static final IBizError INVALID_PARAM = new BizError(600001, "参数错误");
public static final IBizError SQL_EXECUTE_EXCEPTION = new BizError(600002, "SQL执行错误");
public static final IBizError SYSTEM__UNCATCH_ERROR = new BizError(699999, "系统内部错误,请重试");
protected int code;
protected String message;
protected BizError(int code, String message) {
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}
1.4 辅助类BizAsserts
public class BizAsserts {
public static void isNull(Object obj, IBizError bizError) {
isNull(obj, bizError, null);
}
public static void isNull(Object obj, IBizError bizError, String extendMessage) {
if (!ObjectUtil.isNull(obj)) {
throw new BizException(bizError, extendMessage);
}
}
public static void isNotNull(Object obj, IBizError bizError) {
isNotNull(obj, bizError, null);
}
public static void isNotNull(Object obj, IBizError bizError, String extendMessage) {
if (ObjectUtil.isNull(obj)) {
throw new BizException(bizError, extendMessage);
}
}
public static void isTrue(boolean expression, IBizError bizError) {
isTrue(expression, bizError, null);
}
public static void isTrue(boolean expression, IBizError bizError, String extendMessage) {
if (!expression) {
throw new BizException(bizError, extendMessage);
}
}
}
1.5 工具类ObjectUtil
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
public class ObjectUtil {
public static boolean isNull(Object obj) {
if (obj == null) return true;
else if (obj instanceof CharSequence) return ((CharSequence) obj).length() == 0;
else if (obj instanceof Collection) return ((Collection) obj).isEmpty();
else if (obj instanceof Map) return ((Map) obj).isEmpty();
else if (obj.getClass().isArray()) return Array.getLength(obj) == 0;
return false;
}
}
1.6 全局异常处理类BizExceptionHandler
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
@ControllerAdvice
public class BizExceptionHandler {
@ResponseBody
@ExceptionHandler(BizException.class)
public HttpApiResponse<Object> handle(HttpServletResponse httpServletResponse, BizException ex) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return HttpApiResponse.newErrorInstance(ex.getBizError());
}
@ResponseBody
@ExceptionHandler(Exception.class)
public HttpApiResponse handle(HttpServletResponse httpServletResponse, Exception ex) {
httpServletResponse.setStatus(HttpStatus.OK.value());
BizException bex = includeBizException(ex, 0);
if (null == bex) {
return HttpApiResponse.newErrorInstance(BizError.SYSTEM__UNCATCH_ERROR);
}
return HttpApiResponse.newErrorInstance(bex.getBizError());
}
/**
* 有些场景下,BizException会被其他组件/代码重新封装,所以这里通过查找n层异常来判断是否包含BizException
*
* @param ex
* @param level
* @return
*/
private BizException includeBizException(Throwable ex, int level) {
if (null == ex || level >= 5) {
return null;
}
if (ex instanceof BizException) {
return (BizException)ex;
}
return includeBizException(ex.getCause(), ++level);
}
}
2 使用
各模块可以继承BizError来声明自己的业务编码,如
public class UamBizError extends BizError {
public static final IBizError ACCESS_LIMIT = new UamBizError(601003, "无权限访问");
public static class User {
public static final IBizError USER_NOT_FOUND = new UamBizError(601004, "用户不存在");
public static final IBizError EMAIL_INVALID = new UamBizError(601005, "email格式错误");
}
protected UamBizError(int code, String message) {
super(code, message);
}
}
3 示例
throw new BizException(BizError.INVALID_PARAM); // 显式抛出业务异常
BizAsserts.isNotNull(user, BizError.User.USER_NOT_FOUND);