记录日志处理的一种方式

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统一拦截

 

 

 

 

以上是关于记录日志处理的一种方式的主要内容,如果未能解决你的问题,请参考以下文章

Python之日志处理 logging模块

Python之日志处理(logging模块)

logging模块

logging模块

Spring AOP

logging模块全总结