1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

基于aop的日志记录方式实现

说明

最近有个项目需要增加日志记录功能,因为这个项目原来是基于spring开发的,在查阅了相关资料以后,我采用了spring aop的方式实现该需求,然后就有了本篇文章。

思路

我这边需求是这样的:要统计各个接口的调用次数,然后我想加上客户端ip、请求参数、返回结果等信息,而我的接口都是通过controller实现的,所以从原理上讲就是要通过aop拦截所有controller,实现日志记录。项目本身用到了swagger,每个接口都有ApiOperation注解,所以我的实现方式就变成了拦截ApiOperation注解,为什么要拦截ApiOperation,因为ApiOperation注解有对每个接口的描述信息,当然也是因为每个接口方法上都有ApiOperation注解,当然如果你愿意你也可以拦截RequestMapping,下面是我的aop实现:

package com.mytest.aop;

import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @program: publicCoreServer
 * @description: aop 打印 接收参数日志
 * @author: liu yan
 * @create: 2019-11-21 09:15
 */


@Aspect
@Component//定义一个切面
public class LogRecordAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogRecordAspect.class);

    private static final String UTF_8 = "utf-8";

    @Autowired
    private UpmsLogService upmsLogService;


    @Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
    public void logPointCut() {

    }


    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        saveSysLog(point, beginTime, time, result);

        return result;
    }

    /**
     * 日志记录
     *
     * @param joinPoint
     * @param beginTime 开始时间
     * @param spendTime  用时
     * @param result  返回结果
     */
    private void saveSysLog(ProceedingJoinPoint joinPoint,long beginTime, long spendTime, Object result) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        UpmsLog upmsLog = new UpmsLog();
        upmsLog.setLogId(UUIDUtil.getUUID());
        upmsLog.setAppId("wx");

        ApiOperation annotation = method.getAnnotation(ApiOperation.class);
        if(annotation != null){
            //注解上的描述
            upmsLog.setDescription(annotation.value());
        }

        //请求的参数
        Object[] args = joinPoint.getArgs();
        String params = JSON.toJSONString(args[0]);
        upmsLog.setParameter(params);


        // 返回结果
        String resultJson = JSON.toJSONString(result);
        upmsLog.setResult(resultJson);

        //获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        //设置IP地址
        upmsLog.setIp(IPUtils.getIpAddr(request));
        // 请求路径
        String requestUrl = request.getRequestURL().toString();
        upmsLog.setUrl(requestUrl);
        String requestURI = request.getRequestURI();
        upmsLog.setUri(requestURI);

        // 请求头
        String agentString = request.getHeader("User-Agent");
        upmsLog.setUserAgent(agentString);

        // 请求方式
        String authType = request.getMethod();
        upmsLog.setMethod(authType);

        //用户名
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            Object userId = subject.getPrincipal();
            upmsLog.setUsername(userId.toString());
            upmsLog.setUserId(userId.toString());
        }

        String path = request.getContextPath();
        String baseURL =  request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
        upmsLog.setBasePath(baseURL);

        // 开始时间
        upmsLog.setStartTime(beginTime);
        // 用时
        upmsLog.setSpendTime(spendTime);
        upmsLog.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        //保存系统日志
        logger.info("日志信息:"+ upmsLog);
        upmsLogService.saveLog(upmsLog);
    }


}

我的spring xml的配置如下:

 <context:component-scan
            base-package="com.mytest.aop">
        <context:include-filter type="annotation"
                                expression="org.aspectj.lang.annotation.Aspect" />
    </context:component-scan>

    <!-- 设置AOP为自动代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

我的controller(部分)

@Api(value = "info", description = "相关控制器")
@Controller
@RequestMapping(value = "/test/getInfo")
public class InfoController {

    @Autowired
    private InfoService infoService;

    @ApiOperation(value = "aop日志测试")
    @RequestMapping("/getInfo")
    @ResponseBody
    public AjaxJson getInfo(String datas) {
        JSONObject data = JSONObject.parseObject(datas);

        AjaxJson result = infoService.getInfo(data.toString());
        return result;
    }
}

其他的servic、entity等代码这里就不放了,有需求的小伙伴可以留言。

解释

这里简单说明下,aop的实现中最核心最重要的就是切点的定义,也就是如下代码:

 @Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
    public void logPointCut() {

    }

上面定义了类型为注解的切点,切点方法及方式如下:

 @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        saveSysLog(point, beginTime, time, result);

        return result;
    }

我们aop作用的方式是Around,也就是环绕,为啥要用这个,因为我们要拿到方法的入参和返回值,所以这个就是最优解。对于aop,好多知识点早都忘记了,而且平时基本没有用到过,后面一定要抽时间做一次研究,深入探讨一下。

最近确实没有太多时间来学习,而且晚上回来太晚了,家里也没有电脑,只能利用周末时间来学习、整理和总结。再过段时间,尽量保证每天能抽时间写点东西,谢谢大家支持,晚安!

posted @ 2019-11-23 23:47  云中志  阅读(453)  评论(0编辑  收藏  举报