一大早,小王就急匆匆的跑过来找我,说:周哥,那个记录日志的性能我想求教一下。
因为公司某个我的项目要跟别的平台做对接,咱们这边须要给他们提供一套接口。昨天,我就将记录接口日志的工作安顿给了小王。
上面是我跟小王的次要对话。
我:说说怎么了?
小王:我将记录接口日志的性能放到了每个 controller 中,当初感觉有点繁琐,我这样做是不是不太适合?
我:为什么要去每个接口里记录日志?
小王:最开始我是用的拦截器,然而这样一个申请就记录了两条记录。
我:为什么是两条?
小王:在 preHandle 中记录一条申请数据,在 postHandle 中记录一条响应数据。
我:。。。你不是说你会 Aop 吗?
小王:Aop 也是一样,在前置告诉记录一条申请数据,后置告诉记录一条响应数据。
小王:这个数据和以前记录操作日志的不太一样,以前只须要在前置告诉记录一条操作日志就能够了,然而当初有响应,所以只能在 controller 中记录日志了。
我:那你知不知道有个盘绕告诉?你说一下 Aop 就几种告诉类型。
小王:总共有五种,别离是:
- 前置告诉:在咱们执行指标办法之前运行(@Before)
- 后置告诉:在咱们指标办法运行完结之后,不论有没有异样(@After)
- 返回告诉:在咱们的指标办法失常返回值后运行(@AfterReturning)
- 异样告诉:在咱们的指标办法出现异常后运行(@AfterThrowing)
- 盘绕告诉:指标办法的调用由盘绕告诉决定,即你能够决定是否调用指标办法,joinPoint.procced()就是执行指标办法的代码。盘绕告诉能够管制返回对象(@Around)
接下来,咱们一起来演示一下如何应用盘绕告诉来解决小王的问题。
第一步:提供接口用来接管参数和响应接口
@RestController
public 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===19
proceed ====Java 旅途
咱们之所以能够用盘绕告诉来解决小王的问题。其中一个重要的起因就是,咱们提供的所有接口都是通过对立加密的,最初申请的参数都是一个固定的名字 。还须要留神的一点就是, 盘绕告诉的返回值类型必须大于等于办法的返回值,即:退出你办法返回 String 类型,盘绕告诉不能写成 void 类型。
小王看到这里后,豁然开朗,筹备连忙回去试一下。我急忙拉住他。
我:如果接口出现异常了怎么办?
小王:那我在异样告诉里解决就能够了。
我:你再想一下?
小王:如同不行,异样告诉里获取不到申请参数。
我:在盘绕告诉中捕捉解决能够吗?
这时候,看见小王眼睛发光,诧异的说了一句:盘绕告诉太牛批了,居然能够实现前置告诉、后置告诉和异样告诉的工作!
这篇文章戏有点多,别见怪。实战是晋升技术最无效的路径!