springboot自定义注解记录日志

项目验收时被提到日志信息覆盖面不够全,看了一下代码,之前都是在关键的几个方法最后调用SysLogService的insert方法。现在一下子多了几十个方法记录日志的需求,这样一个个增加实在太不优雅了。最后决定自定义注解,用AOP的思想处理。

1、创建SysLog注解


import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {

    //日志描述
    String message() default "";
}

2、配置AOP切点

● 根据 JoinPoint 目标对象,利用反射获取方法名称,方法路径
● 使用 getAnnotationLog() 方法获取 LogMethod 注解
● 使用 IP工具类和 Security 可以获取到用户数据和访问的IP

@Component
@Aspect
@Slf4j
public class RequestAppLogAspect {

    @Resource
    StatFlowExeTraceDao statFlowExeTraceDao;

    private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 切入有SysLog注解的方法
     */
    @Pointcut("@annotation(com.XX.XX.XX.Aspect.SysLog)")
    public void logPointCut() {
    }
    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        //获得注解
        SysLog syslog = method.getAnnotation(SysLog.class);
        //日志类
        StatFlowExeTrace statFlowExeTrace = new StatFlowExeTrace();
        //日志存时间
        statFlowExeTrace.setEXECUTEDT(simpleDateFormat.format(new Date()));
        //获得注解里的message
        statFlowExeTrace.setFLOWNAME(syslog.message());
        statFlowExeTrace.setSITEID(12);
        //记录请求开始执行时间:
        long beginTime = System.currentTimeMillis();
        //获取请求信息
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        String token = request.getHeader(SysConst.USER_TOKEN_HEADER);
        //解析token
        Claims tokenBody = Jwts.parser().setSigningKey("??".getBytes(StandardCharsets.UTF_8)).parseClaimsJws(token).getBody();
        statFlowExeTrace.setACTUSERNAME(MapUtil.getStr(tokenBody,"user_name"));
        //日志存ip
        statFlowExeTrace.setIP(getIpAddr(request));
        //获取代理地址、请求地址、请求类名、方法名
        String requestURI = request.getRequestURI();
        String methodName = pjp.getSignature().getName();
        String clazzName = pjp.getTarget().getClass().getSimpleName();
        //获取请求参数:
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        //获取请求参数类型
        String[] parameterNames = ms.getParameterNames();
        //获取请求参数值
        Object[] parameterValues = pjp.getArgs();
        //参数
        statFlowExeTrace.setPARAMS(sb.toString());
        //方法名
        statFlowExeTrace.setFLOWCOMMAND(methodName);
        Object result = null;
        try {
            //执行原方法
            result = pjp.proceed();
        } catch (Throwable throwable) {
            //请求操纵失败
            //记录错误日志
            log.error("(ง•̀_•́)ง (っ•̀ω•́)っ          切面处理请求错误! " +
                            "URI信息(ง•̀_•́)ง->:【{}】 请求映射控制类(ง•̀_•́)ง->:【{}】 " +
                            "请求方法(ง•̀_•́)ง->:【{}】 请求参数列表(ง•̀_•́)ง->:【{}】", requestURI, clazzName, methodName,
                    sb.toString());
            //交给全局异常处理类处理
            throw throwable;
        }
        //请求操作成功
        statFlowExeTraceDao.insert(statFlowExeTrace);
        return result;
    }
}

上面的代码可以按自己的业务需求自定义。比如说获得用户名、IP、或其他信息。我这边就是把日志类的信息填充完整,然后通过Dao插入数据库。

3、在方法上使用SysLog注解

@ApiOperation(value = "添加单个应用信息", produces = "application/json")
@PostMapping("/addApp")
@SysLog(message ="添加应用" )
public ResponseMessage addApp(@RequestBody AddAppVoA addAppVo) throws Exception {
    return ResponseMessage.ok(appService.addApp(addAppVo));
}

这样就大功告成了,AOP使用动态代理对方法增加,在没有改变原来方法的基础上,实现了日志的记录。

你可能感兴趣的:(SpringBoot,Java,spring,boot,java,spring)