package com.guahao.dap.mi.access.service.impl.utils.aspect;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import com.google.common.collect.HashMultimap;
import com.guahao.dap.mi.access.biz.manager.cache.CodisComponent;
import com.guahao.dap.mi.access.biz.manager.facade.MockFManager;
import com.guahao.dap.mi.access.model.core.po.MockDataPO;
import com.guahao.dap.mi.access.model.core.po.MockGroupPO;
import com.guahao.dap.mi.access.model.core.po.MockGroupTargetPO;
import com.guahao.dap.mi.access.model.core.po.MockRulePO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* mock数据切面类
*
* @author f
* @version V1.0
* @since 2020/8/27 17:20
*/
@Aspect
@Component
public class ExtMockDataAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(ExtMockDataAspect.class);
@Resource
private MockFManager mockFManager;
@Autowired
protected CodisComponent codisComponent;
@Pointcut("@annotation(com.guahao.dap.mi.access.biz.manager.annotation.DealMock)")
public void extMockDataCut() {
}
@Around("extMockDataCut()")
public Object trace(final ProceedingJoinPoint joinPoint) throws Throwable{
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Object[] args = joinPoint.getArgs();
JSONObject param = JSONObject.parseObject(JSONObject.toJSONString(args[0]));
LOGGER.info("切面mock接口请求数据:{}", param.toJSONString());
//获取厂商id
String platformId = param.getString("platformId");
//获取匹配规则
try {
MockRulePO mockPO = mockFManager.getMockRule(method.getName(), platformId);
if (mockPO != null && mockPO.getId() != null) {
List<MockGroupPO> mockGroupPO = mockFManager.getMockGroup(mockPO.getId());
//选出所有的组放入multiMap里面(key-value=int,list)
HashMultimap<Integer, MockGroupPO> linkedListMultimap = HashMultimap.create();
for (MockGroupPO m : mockGroupPO) {
linkedListMultimap.put(m.getFilterGroup(), m);
}
Integer groupId = null;
Map<Integer, Collection<MockGroupPO>> maps = linkedListMultimap.asMap();
//按照map的value(list)的长度降序
LinkedHashMap<Integer, Collection<MockGroupPO>> map = maps.entrySet().stream().sorted(
(o1, o2) -> Integer.compare(o2.getValue().size(), o1.getValue().size()))
.collect(Collectors.
toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
//迭代map,如果命中group即返回groupId
String key;
String[] keys;
JSONObject jsonObject = param;
for (Map.Entry<Integer, Collection<MockGroupPO>> me : map.entrySet()) {
Boolean flag = true;
for (MockGroupPO mo : me.getValue()) {
if (StringUtils.isNotBlank(mo.getFilterKey())) {
keys = mo.getFilterKey().split("\\.");
for (int i = 0, length = keys.length - 1; i < length; ++i) {
jsonObject = jsonObject.getJSONObject(keys[i]) == null ? new JSONObject() : jsonObject.getJSONObject(keys[i]);
}
key = jsonObject.getString(keys[keys.length - 1]) == null ? "" : jsonObject.getString(keys[keys.length - 1]);
if (!StringUtils.equals(key, mo.getFilterValue())) {
flag = false;
}
}
jsonObject = param;
}
if (flag) {
groupId = me.getKey();
break;
}
}
//选出mock数据
if (groupId != null) {
MockGroupTargetPO mockGroupTargetPO = mockFManager.getMockGroupAndTarget(mockPO.getId(), groupId);
MockDataPO mockDataPO = mockFManager.getMockData(mockGroupTargetPO.getId());
LOGGER.info("切面mock接口返回数据:{}", mockDataPO.getData());
List<Type> returnType = getReturnType(method.getGenericReturnType());
return JSONObject.parseObject(mockDataPO.getData(), buildType(returnType));
}
}
}catch (Exception e){
Object result = joinPoint.proceed();
LOGGER.info("切面外部接口返回数据:{}",result);
return result;
}
try{
Object result = joinPoint.proceed();
LOGGER.info("切面外部接口返回数据:{}",result);
return result;
} catch (Exception e) {
LOGGER.error("mock切面执行proceed出现异常:{}",e);
throw e;
}
}
/**
* 递归获取全部返回类的类型值
*/
private List<Type> getReturnType(Type genericReturnType) {
if (genericReturnType == null) {
return null;
}
Type rootType = genericReturnType;
List<Type> typeList = new ArrayList<>();
//获取原始返回值类型
typeList.add(rootType);
if (rootType instanceof ParameterizedType) {
//获取泛型,包括泛型中的泛型
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
//判断泛型里是否有泛型
if (actualTypeArgument instanceof ParameterizedType) {
typeList.addAll(getReturnType(actualTypeArgument));
} else {
typeList.add(actualTypeArgument);
}
}
}
if (!CollectionUtils.isEmpty(typeList)) {
return typeList;
} else {
return null;
}
}
/**
* 拼接返回数据类型ParameterizedTypeImpl
* @param types
* @return
*/
private static Type buildType(List<Type> types) {
ParameterizedTypeImpl beforeType = null;
if (types != null && types.size() > 0) {
for (int i = types.size() - 1; i > 0; i--) {
beforeType = new ParameterizedTypeImpl(new Type[] { beforeType == null ? types.get(i) : beforeType },
null, types.get(i - 1));
}
}
return beforeType;
}
}
利用切面进行mock测试(运用到guava的map)
最新推荐文章于 2024-05-07 19:36:24 发布