通过AOP拦截接口请求,计算接口访问时间,并存入数据库从而统计程序所有接口的访问效率,从而达到针对性优化策略,下面我直接通过代码进行讲解。
package com.wk.zh.admin.constants;
import com.alibaba.fastjson.JSONArray;
import com.wk.zh.admin.model.SysInterfaceLog;
import com.wk.zh.admin.service.SysInterfaceLogService;
import com.wk.zh.common.utils.HNUtil;
import com.wk.zh.common.web.RequestLocalHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;
/**
* 接口日志
* @author wake-曹文斌
* @date Oct 29, 2020
*/
@Aspect
@Component
public class AspectAPIMoinitor {
/**
* 统计API接口调用耗时(方法调用的时间)
* @param joinPoint
* @throws Throwable
*/
@Autowired
private SysInterfaceLogService sysInterfaceLogService;
@Around("execution(public * com.wk.zh.*.controller.*.*(..))")
public Object logServiceMethodAccess(ProceedingJoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Date startDate = new Date();
long start = System.currentTimeMillis();//开始时间
Object object = joinPoint.proceed();
Date endDate = new Date();
long end = System.currentTimeMillis();//介绍绍时间
long takeTime = end - start;//执行需要时间
String className = joinPoint.getSignature().toString();//类名和方法
String token = RequestLocalHelper.getIntance().getToken();
SysInterfaceLog sysInterfaceLog = new SysInterfaceLog();
sysInterfaceLog.setId(HNUtil.getId());//id
sysInterfaceLog.setRequestUrl(request.getRequestURL().toString());//请求url
sysInterfaceLog.setRequestToken(RequestLocalHelper.getIntance().getToken()); //用户token
sysInterfaceLog.setHttpMethod(request.getMethod());//请求方式
sysInterfaceLog.setClassName(className); //请求的方法名
sysInterfaceLog.setReqestParas(JSONArray.toJSON(joinPoint.getArgs()).toString() + ":" + Arrays.toString(joinPoint.getArgs()));//传入参数
sysInterfaceLog.setTakeTime(takeTime);//执行时间
sysInterfaceLog.setCreateTime(new Date());//创建时间
if (null != token)
sysInterfaceLog.setUserId(RequestLocalHelper.getIntance().getUserId());//用户id
sysInterfaceLogService.save(sysInterfaceLog);
return object;
}
}
注解@Around
Spring AOP 切面@Around注解的具体使用
@Around注解可以用来在调用一个具体方法前和调用后来完成一些具体的任务。
比如我们想在执行controller中方法前打印出请求参数,并在方法执行结束后来打印出响应值,这个时候,我们就可以借助于@Around注解来实现;
再比如我们想在执行方法时动态修改参数值等类似功能的注解还有@Before等等,用到了Spring AOP切面思想,Spring AOP常用于拦截器、事务、日志、权限验证等方面。
ProceedingJoinPoint
org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。
HttpServletRequest
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
了解了使用的三个对象后,从对象中取出我们所需要的数据,接口的执行时间,请求的url,用户的token,请求方式,请求方法名,请求的参数,这些都是查找接口所必须的数据。我们将这些数据存入数据库。
long start = System.currentTimeMillis();//开始时间
Object object = joinPoint.proceed();
long end = System.currentTimeMillis();//介绍绍时间
long takeTime = end - start;//执行需要时间
request.getRequestURL().toString();//请求url
RequestLocalHelper.getIntance().getToken(); //用户token
request.getMethod();//请求方式
joinPoint.getSignature().toString(); //请求的方法名
JSONArray.toJSON(joinPoint.getArgs()).toString();//传入参数
我们可以通过这些数据统计出所有接口访问的平均时长,访问时间最长的记录等等。有了这些数据后,我们就可以针对性的对接口进行优化,根据日志记录的信息,传入的参数,访问的用户,接口的性能也更加透明。
SELECT * FROM sys_Interface_log;
#1.查询所有接口的平均时长
SELECT request_url,AVG(take_time) FROM sys_Interface_log
GROUP BY request_url
ORDER BY AVG(take_time) DESC;
#2.获取所有接口最大时长记录
SELECT request_url,MAX(take_time) FROM sys_Interface_log
GROUP BY request_url
ORDER BY MAX(take_time) DESC;
#3.查询所有接口访问时间超过200毫秒的记录
SELECT request_url,COUNT(1) FROM sys_Interface_log
WHERE take_time > 200
GROUP BY request_url
ORDER BY COUNT(1) DESC;
#4.查询所有接口访问时间的最大值和最小值
SELECT request_url,MAX(take_time),MIN(take_time) FROM sys_Interface_log
GROUP BY request_url
ORDER BY MAX(take_time) DESC;
#5.查询接口访问次数
SELECT request_url,COUNT(1) FROM sys_Interface_log
GROUP BY request_url
ORDER BY COUNT(1) DESC;