统一项目数据格式,统一异常管理便于更好的定位项目问题。
由于自我实现有项目业务原因,把主要的接口与思路分享,可自由实现自我适合的业务异常链路。
核心思路:类似于filter责任链处理方式。
chain :管理handler执行链路
handler:处理特定异常的处理器(我使用自定义处理标记处理器);
abstract
统一抽象异常类,抛出的自定义业务异常须继承此类
package com.ygy.exception.model;
import com.ygy.exception.enums.ExceptionCodeEnum;
import com.ygy.exception.enums.ModuleCodeEnum;
import com.ygy.exception.helper.ExceptionCodeHelper;
/**
* Created by guoyao on 2018/2/23.
* 自定义基础异常
*/
public abstract class AbstractException extends RuntimeException {
public AbstractException(String msg) {
super(msg);
this.msg=msg;
}
public String getExceptionCode() {
ExceptionCodeEnum exceptionCodeEnum=getCodeEnum();
ModuleCodeEnum moduleEnum=getModuleCodeEnum();
String subCode=getSubCode();
return ExceptionCodeHelper.getExceptionCode(exceptionCodeEnum,moduleEnum,subCode);
}
protected abstract ModuleCodeEnum getModuleCodeEnum();
protected abstract ExceptionCodeEnum getCodeEnum();
protected abstract String getSubCode();
private String code;
private String msg;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code=code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg=msg;
}
}
helper
异常码helper构建类
package com.ygy.exception.helper;
import com.ygy.exception.enums.ExceptionCodeEnum;
import com.ygy.exception.enums.ExceptionSubCodeEnum;
import com.ygy.exception.enums.ModuleCodeEnum;
import org.apache.commons.lang3.StringUtils;
/**
* Created by guoyao on 2018/2/28.
* 异常组合工具类
*/
public class ExceptionCodeHelper {
/**
* 获取默认异常码
* @return
*/
public static String getExceptionCode() {
return getUnknownCode(ModuleCodeEnum.UNKNOWN_MODULE);
}
/**
* 根据enum获取未知异常码
* @return
*/
public static String getUnknownCode(ModuleCodeEnum moduleCodeEnum) {
return getExceptionCode(ExceptionCodeEnum.UNKNOWN_CDOE, moduleCodeEnum, ExceptionSubCodeEnum.ERP_UNKNOWN_EXCEPTION.getCode());
}
/**
* 根据enum获取基础异常码
*
* @return
*/
public static String getNormalCode(ModuleCodeEnum moduleCodeEnum, ExceptionSubCodeEnum exceptionSubCodeEnum) {
return getExceptionCode(ExceptionCodeEnum.NORMAL_CDOE, moduleCodeEnum, exceptionSubCodeEnum.getCode());
}
/**
* 根据enum获取业务异常码
*
* @return
*/
public static String getBizCode(ModuleCodeEnum moduleCodeEnum, String subCode) {
return getExceptionCode(ExceptionCodeEnum.BIZ_CDOE, moduleCodeEnum, subCode);
}
/**
* 根据enum获取异常码
* @param exceptionCodeEnum
* @param moduleCodeEnum
* @param subCode
* @return
*/
public static String getExceptionCode(ExceptionCodeEnum exceptionCodeEnum, ModuleCodeEnum moduleCodeEnum, String subCode) {
if (exceptionCodeEnum == null) {
exceptionCodeEnum=ExceptionCodeEnum.UNKNOWN_CDOE;
}
if (moduleCodeEnum == null) {
moduleCodeEnum=ModuleCodeEnum.UNKNOWN_MODULE;
}
if (StringUtils.isEmpty(subCode)) {
subCode=ExceptionSubCodeEnum.ERP_UNKNOWN_EXCEPTION.getCode();
}
return new StringBuilder().append(exceptionCodeEnum.getCode()).append(moduleCodeEnum.getCode()).append(subCode).toString();
}
}
param
异常传递参数,可自由添加自己项目中特有的异常追踪id,api_name等标记
package com.ygy.exception.model;
import com.ygy.exception.enums.ModuleCodeEnum;
/**
* Created by guoyao on 2018/3/1.
* 异常处理传递可选参数,可扩展
*/
public class ExceptionParams {
private Object extraParam;
private ModuleCodeEnum moduleCodeEnum;
public Object getExtraParam() {
return extraParam;
}
public ExceptionParams setExtraParam(Object extraParam) {
this.extraParam=extraParam;
return this;
}
public ModuleCodeEnum getModuleCodeEnum() {
return moduleCodeEnum;
}
public ExceptionParams setModuleCodeEnum(ModuleCodeEnum moduleCodeEnum) {
this.moduleCodeEnum=moduleCodeEnum;
if (moduleCodeEnum == null) {
this.moduleCodeEnum=ModuleCodeEnum.UNKNOWN_MODULE;
}
return this;
}
}
handler
业务异常执行器接口,可以进行特定异常的单独处理,也可以统一处理特定类型异常
package com.ygy.exception.handler;
import com.ygy.exception.model.ExceptionParams;
import com.ygy.exception.model.ResultBean;
import com.ygy.exception.chain.ExceptionHandlerChain;
/**
* Created by guoyao on 2018/2/23.
* 异常处理器,对特定异常处理方式。
*/
public interface ExceptionHandler {
public ResultBean handlerException(Exception e, ExceptionParams params, ExceptionHandlerChain chain);
}
package com.ygy.exception.handler;
import com.ygy.exception.model.AbstractException;
import com.ygy.exception.model.ExceptionParams;
import com.ygy.exception.model.ResultBean;
import com.ygy.exception.annotation.ExceptionHandler;
import com.ygy.exception.chain.ExceptionHandlerChain;
import org.springframework.stereotype.Component;
/**
* Created by guoyao on 2018/2/25.
* 自定义业务异常 统一处理异常
*/
@Component
@ExceptionHandler(order = "100")
public class AbstractExceptionHandler implements com.ygy.exception.handler.ExceptionHandler {
@Override
public ResultBean handlerException(Exception e, ExceptionParams exceptionParams, ExceptionHandlerChain chain) {
if (e instanceof AbstractException) {
return ResultBean.ofError((AbstractException) e, exceptionParams);
}
return chain.doHandler(e,exceptionParams);
}
}
chain
handler执行链路接口,管理加载的handler进行业务处理
package com.ygy.exception.chain;
import com.ygy.exception.model.ExceptionParams;
import com.ygy.exception.model.ResultBean;
/**
* Created by guoyao on 2018/2/25.
* 异常处理链接口,可自己实现链路处理方式
*/
public interface HandlerChain {
public ResultBean doHandler(Exception e, ExceptionParams exceptionParams);
}
package com.ygy.exception.chain;
import com.ygy.exception.model.ExceptionParams;
import com.ygy.exception.model.ResultBean;
import com.ygy.exception.handler.ExceptionHandler;
import com.ygy.exception.handler.listener.ExceptionHandlerListener;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
/**
* Created by guoyao on 2018/2/25.
* 异常处理链路
*/
@Component
@Scope("prototype")
public class ExceptionHandlerChain implements HandlerChain {
private int cursor=0;
@Resource
ExceptionHandlerListener exceptionHandlerListener;
public ResultBean doHandler(Exception e, ExceptionParams exceptionParams) {
ArrayList<ExceptionHandler> handlers=exceptionHandlerListener.getHandlers();
if (CollectionUtils.isEmpty(handlers)) {
return ResultBean.ofError(exceptionParams);
}
if (cursor >= handlers.size()) {
return ResultBean.ofError(exceptionParams,"系统异常,异常处理链路达到上限");
}
ResultBean resultBean=handlers.get(cursor++).handlerException(e, exceptionParams, this);
if (resultBean == null) {
resultBean = ResultBean.ofError(exceptionParams);
}
return resultBean;
}
}