HookAspect.java
package io.featureprobe.api.aop;
import io.featureprobe.api.auth.TokenHelper;
import io.featureprobe.api.base.hook.Action;
import io.featureprobe.api.base.hook.IHookQueue;
import io.featureprobe.api.base.hook.Resource;
import io.featureprobe.api.base.hook.Hook;
import io.featureprobe.api.base.model.HookContext;
import io.featureprobe.api.base.tenant.TenantContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Objects;
@Slf4j
@Aspect
@Component
public class HookAspect {
@javax.annotation.Resource
IHookQueue hookQueue;
@Pointcut("@annotation(io.featureprobe.api.base.hook.Hook)")
public void hook (){}
@Around("hook()")
public Object around(ProceedingJoinPoint jp) throws Throwable {
Hook webHookAnnotation = getMethodAnnotation(jp, Hook.class);
Action action = webHookAnnotation.action();
Resource resource = webHookAnnotation.resource();
HookContext context = new HookContext(resource, action);
context.setOperator(TokenHelper.getAccount());
context.setOrganizationId(Long.parseLong(TenantContext.getCurrentTenant()));
Object ret = jp.proceed();
composeParam(jp, context);
context.setResponse(ret);
hookQueue.push(context);
return ret;
}
private void composeParam(ProceedingJoinPoint jp, HookContext context) {
Object requestBody = getRequestBody(jp);
if (Objects.nonNull(requestBody)) {
context.setRequest(requestBody);
}
String projectKey = getProjectKeyArg(jp);
if (StringUtils.isNotBlank(projectKey)) {
context.setProjectKey(projectKey);
}
String environmentKey = getEnvironmentKeyArg(jp);
if(StringUtils.isNotBlank(environmentKey)) {
context.setEnvironmentKey(environmentKey);
}
String toggleKey = getToggleKeyArg(jp);
if (StringUtils.isNotBlank(toggleKey)) {
context.setToggleKey(toggleKey);
}
String segmentKey = getSegmentKeyArg(jp);
if (StringUtils.isNotBlank(segmentKey)) {
context.setSegmentKey(segmentKey);
}
Long id = getIdArg(jp);
if (Objects.nonNull(id)){
context.setId(id);
}
}
private Object getRequestBody(ProceedingJoinPoint jp) {
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Object[] args = jp.getArgs();
for (int i = 0 ; i < parameterAnnotations.length; i++) {
for (Annotation annotation : parameterAnnotations[i]) {
if (annotation instanceof RequestBody) {
return args[i];
}
}
}
return null;
}
private String getProjectKeyArg(ProceedingJoinPoint jp) {
Object projectKey = getPathArg(jp, "projectKey");
if (Objects.isNull(projectKey)) {
return null;
}
return String.valueOf(projectKey);
}
private String getEnvironmentKeyArg(ProceedingJoinPoint jp) {
Object environmentKey = getPathArg(jp, "environmentKey");
if (Objects.isNull(environmentKey)) {
return null;
}
return String.valueOf(environmentKey);
}
private String getToggleKeyArg(ProceedingJoinPoint jp) {
Object toggleKey = getPathArg(jp, "toggleKey");
if (Objects.isNull(toggleKey)) {
return null;
}
return String.valueOf(toggleKey);
}
private String getSegmentKeyArg(ProceedingJoinPoint jp) {
Object segmentKey = getPathArg(jp, "segmentKey");
if (Objects.isNull(segmentKey)) {
return null;
}
return String.valueOf(segmentKey);
}
private Long getIdArg(ProceedingJoinPoint jp) {
Object idArg = getPathArg(jp, "id");
Long id = null;
if (Objects.isNull(idArg)) {
return null;
}
try {
id = (Long) idArg;
} catch (Exception e) {
return null;
}
return id;
}
private Object getPathArg(ProceedingJoinPoint jp, String name) {
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Object[] args = jp.getArgs();
for (int i = 0 ; i < parameterAnnotations.length; i++) {
for (Annotation annotation : parameterAnnotations[i]) {
if (annotation instanceof PathVariable && ((PathVariable) annotation).value().equals(name)) {
return args[i];
}
}
}
return null;
}
private <T extends Annotation> T getMethodAnnotation(JoinPoint joinPoint, Class<T> clazz) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
return method.getAnnotation(clazz);
}
}