Spring Boot 使用AOP将日志存入MongoDB

虽然网上已经有很多使用AOP存入日志了,但我这个不一样。

1.使用最简单的代码直接从注解中获取值

2.支持SEL表达式获取参数中的值

注意事项:如果不用MongoDB就换成自己的方式,简单改一下罗。上代码了。

1.创建AOP拦截类 基本结构不用多说了

Spring Boot 使用AOP将日志存入MongoDB_第1张图片

2.重点来了,将注解作为参数直接传入,即可直接获取注解中的值。无需通过反射获取。

/**
     * 需要切入的注解
     */
    @Pointcut("@annotation(post2netAnno)")
    public void initPost2netAnno(Post2MongodbAnno post2netAnno) {
    }

    @Before("initPost2netAnno(post2netAnno)")
    public void doBefore(JoinPoint joinPoint, Post2MongodbAnno post2netAnno) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //url
        log.info("url={}",request.getRequestURL());
        //method
        log.info("method={}",request.getMethod());
        //ip
        log.info("id={}",request.getRemoteAddr());
        //class_method
        log.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName() + "," + joinPoint.getSignature().getName());
        //args[]
        ObjectMapper mapper = new ObjectMapper();
        try {
            String param = mapper.writeValueAsString(joinPoint.getArgs());
            log.info("args={}",param);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }


    @Around("initPost2netAnno(post2netAnno)")
    public Object around(ProceedingJoinPoint pjp, Post2MongodbAnno post2netAnno) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object  o = null;
        Object[] args = pjp.getArgs();

        final Object param = args[0];

        StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext(pjp.getArgs());
        standardEvaluationContext = setContextVariables(standardEvaluationContext, pjp);

        try {
                o = pjp.proceed();
                sava2mogodb(standardEvaluationContext,post2netAnno,param,o,System.currentTimeMillis() - startTime);
                log.info("☢☢☢:执行结果:{}",o);
                return o;
        }catch (Exception e){
           //其他运行异常统一处理
            log.error(e.toString()+":"+e.getMessage());
            e.printStackTrace();
            Result re =  Result.buildFail();
            re.setMsg(e.getMessage());
            sava2mogodb(standardEvaluationContext,post2netAnno,param,re,System.currentTimeMillis() - startTime);
            return re;
        }
    }

3.通过SEL表达式获取 参数中的值

 private StandardEvaluationContext setContextVariables(StandardEvaluationContext standardEvaluationContext, ProceedingJoinPoint joinPoint) {

        Object[] args = joinPoint.getArgs();

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

        Method targetMethod = methodSignature.getMethod();

        LocalVariableTableParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();

        String[] parametersName = parameterNameDiscoverer.getParameterNames(targetMethod);

        if(args ==null|| args.length<=0) {

            return standardEvaluationContext;

        }
        for(int i =0;i < args.length;i++) {

            standardEvaluationContext.setVariable(parametersName[i],args[i]);

        }
        return standardEvaluationContext;
    }

    /**
     * 通过key SEL表达式获取值
     * @Author 张鹏
     * @Date 2018/8/24 15:22
     * @param key
     * @param context
     * @return
     */
    private String getElValue(String key,StandardEvaluationContext context) {
        if(StringUtils.isBlank(key)){
            return "";
        }
        ExpressionParser parser =new SpelExpressionParser();

        Expression exp = parser.parseExpression(key);

        String value = exp.getValue(context,String.class);

        return value;

    }

4.大功告成,看看如何使用吧

Spring Boot 使用AOP将日志存入MongoDB_第2张图片

框起来的就是SEL表达式罗。

注解中的内容怎么定义,我就不多说了。该有的关键代码已经全部加上去了

你可能感兴趣的:(Spring,Boot)