记录日志处理的一种方式
Posted z-xiaoyao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录日志处理的一种方式相关的知识,希望对你有一定的参考价值。
根据现在我们itoo的结构,结合开发过程中开发人员对日志使用情况的反馈,以下是我对日志处理的一种新的方式的尝试,仅供大家参考。
Itoo-tool中配置:
首先在itoo-tool中定义的结构如下:
exception包中itooException为itoo异常,继承RuntimeException,代码如下:
public class ItooException extends RuntimeException implements Serializable private Integer code; public ItooException(ItooResultEnum itooResultEnum) super(itooResultEnum.getMessage()); this.code = itooResultEnum.getCode(); public ItooException(Integer code, String message) super(message); this.code = code; public ItooException()
exception包中的handler包为封装web层的异常处理类,其代码如下:
public class ItooExceptionHandler implements Serializable /** * 处理所有不可知的异常 * * @param e 异常 * @return 序列化异常结果 */ @ExceptionHandler(Exception.class) @ResponseBody ResultVo handleException(Exception e) log.error(e.getMessage(), e); return ResultVoUtil.error(1111, e.getMessage());
enums包
enums包中itooResultEnum枚举类定义通用错误码,以及错误描述,被itooException引用,其代码如下:
@Getter public enum ItooResultEnum PARAM_ERROR(1, "参数不正确"), RETURN_ISNULL(2, "返回值为空"), ; private Integer code; private String message; ItooResultEnum(Integer code, String message) this.code = code; this.message = message;
Aspect包
Aspect包中的itooAbstractAspect为切面类,可从各个服务获取异常切点,方法参数切点,以及获取子服务中配置文件的参数,其作用是,检测拦截到的异常是否是itooexception或者itooexception的子类,如果不是则转为itooexception(避免产生classnotfound覆盖真正的异常)其代码如下:
//定义切面 @Aspect @Slf4j public abstract class ItooAbstractAspect implements Serializable //定义异常切点 @Pointcut protected abstract void exceptionPointCut(); //定义方法参数切点 @Pointcut protected abstract void methodsPointCut(); // 获取配置文件中的参数 protected abstract Map<String, Boolean> getConfigMap(); /** * 执行方法之前执行 * * @param joinPoint */ @Before("methodsPointCut()") public void before(JoinPoint joinPoint) if (true != getAopStatus("before") ) return; StringBuilder str = getMethodsInfo(joinPoint); if (CollectionUtils.arrayToList(joinPoint.getArgs()).isEmpty()) str.append("该方法没有参数"); else StringBuilder strArgs = new StringBuilder("参数为:"); for (Object o : joinPoint.getArgs()) strArgs.append(o + ","); str.append(strArgs); System.out.println(str.toString()); /** * 方法正常结束之后执行 * * @param retrunvalue */ @AfterReturning(value = "methodsPointCut()", returning = "retrunvalue") public void afterReturning(JoinPoint joinPoint, Object retrunvalue) if (true != getAopStatus("afterreturning") ) return; StringBuilder str = getMethodsInfo(joinPoint); str.append("返回值为:" + retrunvalue); System.out.println(str); private Boolean getAopStatus(String aopName) final Map<String, Boolean> configMap = getConfigMap(); if (configMap == null) return null; if (true != configMap.get(aopName)) return false; return true; private StringBuilder getMethodsInfo(JoinPoint joinPoint) StringBuilder str = new StringBuilder(); String classname = joinPoint.getTarget().getClass().getSimpleName(); String methodName = joinPoint.getSignature().getName(); str.append("类:" + classname + ";" + "执行了方法:" + methodName + ";"); return str; /** * 方法执行过程中发生异常时执行该方法 * * @param e */ @AfterThrowing(value = "exceptionPointCut()", throwing = "e") public void afterThrowing(Throwable e) if (true != getAopStatus("afterthrowing") ) return; if (e instanceof ItooException) try throw e; catch (Throwable throwable) throwable.printStackTrace(); else ItooException itooException = new ItooException(1111, e.getMessage()); throw new ItooException(1111, e.getMessage()); /** * 无论是否正确执行目标方法,都会执行该方法,常用与资源回收 */ // @After(value = "pointCut()") // public void after() // System.out.println("我是after方法我执行了"); // /** * 于Before增强处理和AfterReturing增强,Around增强处理可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标方法的执行 * * @param proceedingJoinPoint */ @Around(value = "methodsPointCut()") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable if (true != getAopStatus("afterthrowing") ) return proceedingJoinPoint.proceed(); StringBuilder str = getMethodsInfo(proceedingJoinPoint); long startTime = System.currentTimeMillis(); //执行方法 Object returnVal = proceedingJoinPoint.proceed(); //计算耗时 long elapsedTime = System.currentTimeMillis() - startTime; str.append("耗时" + elapsedTime + "毫秒"); System.out.println(str); return returnVal;
各子服务配置:
Api配置:
首先在api中新建两个包,enums包中定义自定义异常的枚举类,开发人家可在此建立自己的枚举类,被自定义异常引用(下图是我自定义的枚举类):
Exception包中为开发人员自己定义的异常,如下图为我自定义的异常:
service层配置:
注意:配置后façade层可不用书写try-catch
在service中,建立aspect包,并建立自己服务的配置,开发人员可通过修改默认配合达到自己预期的效果,效果如下:
方法参数切点:默认切入serviceimpl,可更改
异常切点:默认切入serviceimpl,可捕获开发人员throw出的异常系统产生的异常
GetConfigMap:用于读取用户的配置,可配置项如下,用于配置方法方法参数切点切入后想要看到的信息
代码书写
开发人员在service中的实现中,直接抛出自定义的异常(对于开发人员没有抛出的异常异常也会进行拦截)
web层处理:
注意:配置后web层可不用书写try-catch
在web层建立handler包,每个子服务定义一个异常处理Handler即可,该类继承tool中的itooexceptionhandler类,可根据用户自定义异常的不同做不同的处理,最后统一返回ResultVoUtil对象即可。
Web层开发人员代码如下(正常书写即可),如果发生异常会被handler统一拦截
以上是关于记录日志处理的一种方式的主要内容,如果未能解决你的问题,请参考以下文章