需求:统计研发测试云各个功能使用情况,即各项目下各个功能调用次数的统计
初步解决方案:使用SpringAOP切面思想,自定义个注解,将注解放在关键接口上,以这个接口为切入点,当调用具有此注解的接口时对方法进行拦截,获取方法上的RequestMapping或者PostMapping等注解的属性值进行统计。
package com.haiyisoft.cloud.devops.util;
import com.haiyisoft.cloud.devops.web.util.UserViewUtil;
import com.haiyisoft.cloud.jpa.util.JPAUtil;
import com.haiyisoft.cloud.mservice.util.CommonUtil;
import com.haiyisoft.cloud.mservice.util.SequenceUtil;
import com.haiyisoft.cloud.web.annotation.PrimaryAccess;
import com.haiyisoft.cloud.web.annotation.ProjectMapping;
import com.haiyisoft.entity.devops.AccessInterface;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author seanwang
* @version 1.0
* @date 2021/3/1 15:22
* 接口访问记录统计。
*/
@Component
@Aspect
public class InterfaceAccessHandler{
/**
* 定义切面
* Pointcut("execution(* com.haiyisoft.cloud.*.*.controller..*.*(..))")
* com.haiyisoft.cloud.devops.*.controller包及其子包下的所有接口都会被统计
*/
@Pointcut("@annotation(com.haiyisoft.cloud.web.annotation.PrimaryAccess)")
public void pointCut(){
}
/**
* 在接口原有的方法执行前,将会首先执行此处的代码
*/
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String projectIdStr = request.getParameter("projectId");
Long projectId = null;
if (projectIdStr != null){
projectId = Long.parseLong(projectIdStr);
}
//记录请求信息
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
String value = "";
String name = "";
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
value = Arrays.toString(requestMapping.value());
name = requestMapping.name();
}else if (method.isAnnotationPresent(GetMapping.class)) {
GetMapping getMapping = method.getAnnotation(GetMapping.class);
value = Arrays.toString(getMapping.value());
name = getMapping.name();
}else if (method.isAnnotationPresent(PostMapping.class)) {
PostMapping postMapping = method.getAnnotation(PostMapping.class);
value = Arrays.toString(postMapping.value());
name = postMapping.name();
}else if (method.isAnnotationPresent(ProjectMapping.class)) {
ProjectMapping projectMapping = method.getAnnotation(ProjectMapping.class);
value = Arrays.toString(projectMapping.value());
name = projectMapping.name();
}else if (method.isAnnotationPresent(PrimaryAccess.class)) {
PrimaryAccess primaryAccess = method.getAnnotation(PrimaryAccess.class);
value = primaryAccess.accessInterface();
name = primaryAccess.desc();
}
//持久化
collect(value,name,projectId);
}
private void collect(String interfaceName, String interfaceDesc, Long projectId) {
AccessInterface accessInterface = new AccessInterface();
accessInterface.setAccessId(SequenceUtil.genEntitySequenceNo(AccessInterface.class));
accessInterface.setInterfaceUrl(formatUrl(interfaceName));
accessInterface.setInterfaceDesc(interfaceDesc);
accessInterface.setAccessTime(CommonUtil.getDateTime());
accessInterface.setProjectId(projectId);
try {
accessInterface.setAccessUser(UserViewUtil.getUserName());
}catch (NullPointerException e){}
JPAUtil.create(accessInterface);
}
/**
* [/getNoticeCount] ==> /getNoticeCount
*/
private String formatUrl(String url) {
return url.substring(1,url.length()-1);
}
}