AOP如何实现打印接口日志
AOP如何实现打印接口日志,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
我们提供的服务有:成都网站设计、成都网站建设、微信公众号开发、网站优化、网站认证、禹城ssl等。为上千多家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的禹城网站制作公司
接口日志有啥用
在我们日常的开发过程中,我们可以通过接口日志去查看这个接口的一些详细信息。比如客户端的IP,客户端的类型,响应的时间,请求的类型,请求的接口方法等等,我们可以对这些数据进行统计分析,提取出我们想要的信息。
怎么拿到接口日志
这里,我们使用的是Spring的两大杀器之AOP,通过在Controller层定义切点,然后对请求对象进行分析获取接口信息,同时开启一个ThreadLocal来记录响应时间。
关于AOP的注解
@Aspect
:将一个类定义为切面类。@Pointcut
:定义一个切入点。@Before
:在切入点开始处切入内容。@After
:在切入点结尾处切入内容。@AfterReturning
:在切入点返回内容之后切入内容(可以用来对处理返回值做一些加工处理。@Around
:在切入点前后切入内容,并自己控制何时执行切入点自身的内容@AfterThrowing
:用来处理当切入内容部分抛出异常之后的处理逻辑。@Order
:在切入点前的操作,按order的值由小到大执行;在切入点后的操作,按order的值由大到小执行。
实战应用
一:引入依赖
首先,我们需要新增引入aop的依赖,以及用于分析客户端信息的UserAgentUtils包,还有用于@Slf4j
打印日志的Lombok的包:
org.springframework.boot spring-boot-starter-aop eu.bitwalker UserAgentUtils 1.20
二:定义一个ResponseAop切面类
在之前的统一返回值和异常处理中我们已经定义过这个类,这里是对其进行完善。这里我再把代码再写一下:
@Aspect @Order(5) @Component @Slf4j public class ResponseAop
三:定义一个ThreadLocal变量
直接在这里定义基本类型会有同步问题,所以我们定义一个ThreadLocal对象来记录消耗的时间。
ThreadLocalstartTime = new ThreadLocal<>();
四:定义切点
这里需要注意的是切点的写法,一定要正确才能保证AOP生效!这里附上一些简单的写法,后续会单独开一章讲解execution表达式的书写。
任意公共方法:
execution(public * *(..))
任何一个以“set”开始的方法的执行:
execution(* set*(..))
Service接口的任意方法的执行:
execution(* com.xyz.service.Service.*(..))
定义在service包里的任意方法的执行:
execution(* com.xyz.service..(..))
定义在service包和所有子包里的任意类的任意方法的执行:
execution(* com.xyz.service...(..))
/** * 切点 */ @Pointcut("execution(public * indi.viyoung.viboot.*.controller..*(..))") public void httpResponse() { }
五:在@Before中获取请求信息
@Before("httpResponse()") public void doBefore(JoinPoint joinPoint){ //开始计时 startTime.set(System.currentTimeMillis()); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //打印请求的内容 UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));//获取请求头中的User-Agent log.info("接口路径:{}" , request.getRequestURL().toString()); log.info("浏览器:{}", userAgent.getBrowser().toString()); log.info("浏览器版本:{}",userAgent.getBrowserVersion()); log.info("操作系统: {}", userAgent.getOperatingSystem().toString()); log.info("IP : {}" , request.getRemoteAddr()); log.info("请求类型:{}", request.getMethod()); log.info("类方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); log.info("请求参数 : {} " + Arrays.toString(joinPoint.getArgs())); }
六:在@AfterReturning中获取方法的返回值和执行时间
@AfterReturning(returning = "ret" , pointcut = "httpResponse()") public void doAfterReturning(Object ret){ //处理完请求后,返回内容 log.info("方法返回值:{}" , ret); log.info("方法执行时间:{}毫秒", (System.currentTimeMillis() - startTime.get())); }
七:测试结果
下面,我们对一个接口进行访问:
2019-02-21 21:03:31.358 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 接口路径:http://localhost:8090/users 2019-02-21 21:03:31.359 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 浏览器:CHROME 2019-02-21 21:03:31.359 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 浏览器版本:72.0.3626.109 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 操作系统: MAC_OS_X 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : IP : 0:0:0:0:0:0:0:1 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 请求类型:GET 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 类方法 : indi.viyoung.viboot.apilog.controller.UserController.findAll 2019-02-21 21:03:31.360 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 请求参数 : {} [] ... 2019-02-21 21:03:31.393 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 方法返回值:ReturnVO{code='2000', message='操作成功', data=[User(id=10000001, password=123456, userName=vi-young), User(id=10000002, password=123456, userName=vi-young), User(id=10000003, password=123123, userName=lxt), User(id=10000004, password=123456, userName=yangwei)]} 2019-02-21 21:03:31.393 INFO 11788 --- [nio-8090-exec-5] indi.viyoung.viboot.aop.ResponseAop : 方法执行时间:36毫秒
可以看出,我们已经获取到我们想要的信息~
在后面的应用实战中,我们会将这些信息保存到数据库中,并且使用一些数据分析工具进行分析。
关于AOP如何实现打印接口日志问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。
分享名称:AOP如何实现打印接口日志
URL链接:http://azwzsj.com/article/gcsjdj.html