一大早,小王就急匆匆的跑过来找我,说:周哥,那个记录日志的性能我想求教一下。

因为公司某个我的项目要跟别的平台做对接,咱们这边须要给他们提供一套接口。昨天,我就将记录接口日志的工作安顿给了小王。

上面是我跟小王的次要对话。

我:说说怎么了?

小王:我将记录接口日志的性能放到了每个controller中,当初感觉有点繁琐,我这样做是不是不太适合?

我:为什么要去每个接口里记录日志?

小王:最开始我是用的拦截器,然而这样一个申请就记录了两条记录。

我:为什么是两条?

小王:在preHandle中记录一条申请数据,在postHandle中记录一条响应数据。

我:。。。你不是说你会Aop吗?

小王:Aop也是一样,在前置告诉记录一条申请数据,后置告诉记录一条响应数据。

小王:这个数据和以前记录操作日志的不太一样,以前只须要在前置告诉记录一条操作日志就能够了,然而当初有响应,所以只能在controller中记录日志了。

我:那你知不知道有个盘绕告诉?你说一下Aop就几种告诉类型。

小王:总共有五种,别离是:

  • 前置告诉:在咱们执行指标办法之前运行(@Before
  • 后置告诉:在咱们指标办法运行完结之后,不论有没有异样(@After
  • 返回告诉:在咱们的指标办法失常返回值后运行(@AfterReturning
  • 异样告诉:在咱们的指标办法出现异常后运行(@AfterThrowing
  • 盘绕告诉:指标办法的调用由盘绕告诉决定,即你能够决定是否调用指标办法,joinPoint.procced()就是执行指标办法的代码 。盘绕告诉能够管制返回对象(@Around)

接下来,咱们一起来演示一下如何应用盘绕告诉来解决小王的问题。

第一步:提供接口用来接管参数和响应接口

@RestControllerpublic class TestController {    @GetMapping("/getName")    public String getName(HttpServletRequest request) throw Exception {        String result = "Java旅途";        String age = request.getParameter("age");        if("18".equals(age)){            result = "无奈辨认";        }        return result;    }}

第二步:定义切点

execution()是比拟罕用的定义切点的表达式,execution()语法如下:

execution(修饰符  返回值  包.类.办法名(参数) throws异样)

其中:

修饰符和throws异样能够省略不写

依据这些解释,咱们能够将第一步中的接口用execution()表达式来形容一下:

execution(String binzh.website.controller.TestController.GetName(HttpServletRequest))
  • *:匹配所有项
  • ..:匹配任意个办法参数
  • ..呈现在类名中时,前面必须跟*,示意包、子孙包下的所有类;

当初咱们优化一下下面的表达式,定义切面为controller包及controller上面所有包的所有办法

execution(* binzh.website.controller..*.*(..))

第三步:盘绕告诉记录日志

@Around("execution(* binzh.website.controller..*.*(..))")public Object around(ProceedingJoinPoint joinPoint) {    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();    HttpServletRequest request = attributes.getRequest();    String age = request.getParameter("age");    Object proceed = "";    try {        proceed = joinPoint.proceed();    } catch (Throwable e) {        e.printStackTrace();    }    System.out.println("age==="+age);    System.out.println("proceed ===="+proceed);    return proceed;}

运行后果如下:

age===19proceed ====Java旅途

咱们之所以能够用盘绕告诉来解决小王的问题。其中一个重要的起因就是,咱们提供的所有接口都是通过对立加密的,最初申请的参数都是一个固定的名字。还须要留神的一点就是,盘绕告诉的返回值类型必须大于等于办法的返回值,即:退出你办法返回String类型,盘绕告诉不能写成void类型

小王看到这里后,豁然开朗,筹备连忙回去试一下。我急忙拉住他。

我:如果接口出现异常了怎么办?

小王:那我在异样告诉里解决就能够了。

我:你再想一下?

小王:如同不行,异样告诉里获取不到申请参数。

我:在盘绕告诉中捕捉解决能够吗?

这时候,看见小王眼睛发光,诧异的说了一句:盘绕告诉太牛批了,居然能够实现前置告诉、后置告诉和异样告诉的工作!

这篇文章戏有点多,别见怪。实战是晋升技术最无效的路径!