系统日志AOP注解实现

898 阅读1分钟

定义日志注解

/**
 * 自定义操作日志记录注解
 * 
 * Target 表示注解用在什么地方
 * Retention 表示注解保留到什么时候
 * Documented 表示会被javadoc记录
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
    // 模块名
    String module() default "";
    // 功能操作
    String operation() default "";
    // 操作类型
    OperateType operateType() default OperateType.OTHER;
    /** 是否保存请求的参数 */
    boolean saveRequestParam() default true;
}

定义日志切面

@Slf4j
@Aspect
@Component
public class SysLogAspect {
    
    /**
     * 定义切点
     */
    @Pointcut("@annotation(com.xup.common.annotion.SysLog)")
    public void logPointCut() {
    }
    
    /**
     * 环绕
     *
     * @param point 连接点
     * @throws Throwable 异常
     */
    @Around("logPointCut()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        joinPoint.proceed();
        //执行时长(毫秒)
        long executeTime = System.currentTimeMillis() - beginTime;
        
        //保存日志
        handleLog(joinPoint, executeTime, null);
    }
    
    /**
     * 获取注解
     */
    private SysLog getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        
        if (method != null) {
            return method.getAnnotation(SysLog.class);
        }
        return null;
    }
    
    /**
     * 拦截异常操作
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        handleLog(joinPoint,0, e);
    }
    
    protected void handleLog(final JoinPoint joinPoint,long executeTime, final Exception e) {
        try {
            // 获得注解
            SysLog logAnnotation = getAnnotationLog(joinPoint);
            if (logAnnotation == null) {
                return;
            }
            
            // *========数据库日志=========*//
            com.xup.sys.config.entity.SysLog sysLog = new com.xup.sys.config.entity.SysLog();
            sysLog.setStatus(BusinessStatus.SUCCESS.ordinal());
            sysLog.setExecuteTime(executeTime);
            String ip = ShiroUtils.getIp();
            sysLog.setIp(ip);
            sysLog.setUrl(ServletUtils.getRequest().getRequestURI());
            // 获取当前的用户
            User currentUser = ShiroUtils.getSysUser();
            if (currentUser != null) {
                sysLog.setOperator(currentUser.getLoginName());
            }
            
            if (e != null) {
                sysLog.setStatus(BusinessStatus.FAIL.ordinal());
                sysLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            sysLog.setMethod(className + "." + methodName + "()");
            // 处理设置注解上信息
            setAnnotationInfo(sysLog, logAnnotation);
            // TODO 入库操作
        } catch (Exception exp) {
            log.error("日志入库异常:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }
    
    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     * @param sysLog     日志
     * @param logAnnotation 操作日志
     */
    private void setAnnotationInfo(com.xup.sys.config.entity.SysLog sysLog,
           SysLog logAnnotation) {
        sysLog.setModule(logAnnotation.module());
        sysLog.setOperation(logAnnotation.operation());
        sysLog.setOperateType(logAnnotation.operateType().ordinal());
       
        if (logAnnotation.saveRequestParams()) {
            Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
            String params = JSONObject.toJSONString(map);
            sysLog.setParam(StringUtils.substring(params, 0, 2000));
        }
    }

方法上添加注解

@SysLog("保存菜单")
public void save(@RequestBody SysMenu menu){
    
}