概述
官网: https://gitee.com/ForteScarlet/Mock.java
依赖: https://mvnrepository.com/artifact/io.gitee.ForteScarlet/mock.java
代码
二次封装
工具
EnhanceClassUtil.java
package work.linruchang.lrcutilsweb.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.BasicType;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.TypeUtil;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.*;
/**
* @author LinRuChang
* @version 1.0
* @date 2022/10/09
* @since 1.8
**/
public class EnhanceClassUtil extends ClassUtil {
/**
* 获取数组元素的反射,非数组直接返回null
* @param arrayClazz 数组Class
* @return
*/
public static Class getArrayElementClass(Class arrayClazz) {
if(arrayClazz != null && arrayClazz.isArray()) {
return forName(StrUtil.removeAny(arrayClazz.getName(),"[L", ";"));
}
return null;
}
/**
* 某字段的类型是容器,获取其容器的元素类型
* <p>
* List<Long> ==> Long.class
* List ==> Object.class
*
* @param field
* @return
*/
public static Class getCollElemType(Field field) {
Assert.notNull(field, "缺乏字段,请检查");
Assert.isTrue(Collection.class.isAssignableFrom(field.getType()), "入参必须是容器类型的字段,请检查:{}", field);
Type genericType = field.getGenericType();
if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
return (Class) TypeUtil.getTypeArgument(genericType);
} else {
return Object.class;
}
}
public static boolean isNumberType(Class clazz) {
boolean result = false;
if (clazz != null) {
List<? extends Class<? extends Number>> numberClasses = Arrays.asList(Byte.class, Byte.TYPE, Short.class, Short.TYPE, Integer.class, Integer.TYPE, Long.class, Long.TYPE, BigInteger.class, Float.class, Float.TYPE, Double.class,Double.TYPE);
if (CollUtil.contains(numberClasses, clazz)) {
result = true;
} else {
// TODO
}
}
return result;
}
public static boolean isDateType(Class clazz) {
boolean result = false;
if (clazz != null) {
List<Class> dateClasses = Arrays.asList(Date.class, Calendar.class, LocalDate.class, LocalDateTime.class, ZonedDateTime.class,java.sql.Date.class);
if (CollUtil.contains(dateClasses, clazz)) {
result = true;
} else {
// TODO
}
}
return result;
}
/**
* 获取基本变量类型,找不到直接返回null
* @param type 基本变量类型全限定名
* @return
*/
public static Class getBasicType(String type) {
return BasicType.WRAPPER_PRIMITIVE_MAP.values().stream()
.filter(clazz -> StrUtil.equals(type, clazz.getName()))
.findFirst()
.orElse(null);
}
/**
* 获取类型,找不到不抛异常直接返回null
*
* 支持基本类型反射获取
* @param type 类型的全限定名
* @return
*/
public static Class getType(String type) {
return ObjectUtil.defaultIfNull(forName(type), getBasicType(type));
}
/**
* 获取所有父类,不含Object.class
* @param clazz 反射
* @return
*/
public static List<Class> superClasses(Class clazz) {
List<Class> result = CollUtil.newArrayList();
if (clazz != null) {
while (true) {
clazz = clazz.getSuperclass();
if (clazz == Object.class) {
break;
}
result.add(clazz);
}
}
return result;
}
/**
* 获取JDK类型,如果类型非jdk,直接返回null
*
* @param type 类型全限定名
* @return
*/
public static Class getJdkClass(String type) {
Class result = getBasicType(type);
if (result == null) {
result = forName(type);
result = isJdkClass2(result) ? result : null;
}
return result;
}
/**
* 是否是JDK定义的类型
* @param clazz
* @return
*/
public static boolean isJdkClass2(Class clazz) {
if (clazz == null) {
return false;
}
boolean javaFlag = StrUtil.startWithAny(clazz.getName(), "java.", "[Ljava.");
if (!javaFlag) {
return superClasses(clazz).stream()
.anyMatch(superClazz -> StrUtil.startWithAny(superClazz.getName(), "java.", "[Ljava."));
}
return javaFlag;
}
/**
* 获取Class实例 == 获取不到不会抛出异常
* @param type 类全限定名
* @return
*/
public static Class forName(String type) {
try {
return Class.forName(type);
} catch (Exception e) {
return null;
}
}
/**
* 是否【是】普通字段的类型
* @param type 类型全限定名
* @return
*/
public static boolean isBeanFieldJavaType(String type) {
return getJdkClass(type) != null;
}
/**
* 是否【不是】普通字段的类型
* @param type 类型全限定名
* @return
*/
public static boolean isNotBeanFieldJavaType(String type) {
return !isBeanFieldJavaType(type);
}
}
EnhanceRandomUtil.java
package work.linruchang.lrcutilsweb.util;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.forte.util.utils.MockUtil;
/**
* 增强的随机工具类
*
* @author LinRuChang
* @version 1.0
* @date 2022/10/09
* @since 1.8
**/
public class EnhanceRandomUtil extends RandomUtil {
public static Object[] nums(Class numberType, Integer numCount) {
Object[] randomNumsResult = new Object[numCount];
for (int index = 0; index < numCount; index++) {
randomNumsResult[index] = Convert.convert(numberType, randomLong());
}
return randomNumsResult;
}
public static Object[] dates(Class numberType, Integer dateCount) {
Object[] datesResult = new Object[dateCount];
for(int index = 0; index < dateCount; index++) {
datesResult[index] = Convert.convert(numberType, MockUtil.date());
}
return datesResult;
}
public static Boolean[] bools(Integer booleanCount) {
Boolean[] result = new Boolean[booleanCount];
for(int index = 0; index < booleanCount; index++) {
result[index] = randomBoolean();
}
return result;
}
public static Character[] characters(Integer charactersCount) {
Character[] result = new Character[charactersCount];
for(int index = 0; index < charactersCount; index++) {
result[index] = MockUtil.character();
}
return result;
}
}
EnhanceMockUtil.java
package work.linruchang.lrcutilsweb.util;
import cn.hutool.core.convert.BasicType;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReflectUtil;
import com.forte.util.Mock;
import com.forte.util.loader.MethodLoader;
import com.forte.util.mockbean.MockMapBean;
import com.forte.util.utils.MockUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* 增强的{@link MockUtil}
*
* @author LinRuChang
* @version 1.0
* @date 2022/10/08
* @since 1.8
**/
public class EnhanceMockUtil {
private static Object mockRandomData(String dateType) {
Class aClass = EnhanceClassUtil.getJdkClass(dateType);
if (aClass == null) {
return null;
}
boolean isArrayFlag = aClass.isArray();
Integer arrayElemeCount = RandomUtil.randomInt(1, 10);
Object[] result = new Object[0];
// 数组类型
if (isArrayFlag) {
aClass = BasicType.wrap(EnhanceClassUtil.getArrayElementClass(aClass));
} else { // 普通类型
aClass = BasicType.wrap(aClass);
}
//不会有基本类型
Class elementClass = aClass;
if (aClass == String.class) {
result = MockUtil.names(arrayElemeCount);
} else if (EnhanceClassUtil.isNumberType(aClass)) {
result = EnhanceRandomUtil.nums(aClass, arrayElemeCount);
}else if(aClass == Boolean.class) {
result = EnhanceRandomUtil.bools(arrayElemeCount);
}else if(EnhanceClassUtil.isDateType(aClass)) {
result = EnhanceRandomUtil.dates(aClass,arrayElemeCount);
}else if (aClass == Character.class) {
result = EnhanceRandomUtil.characters(arrayElemeCount);
}
return isArrayFlag?result:EnhanceArrayUtil.getFirst(result);
}
/**
* mock数据生成
*
* @param dateType mock的数据类型
* @param proertyName mock的字段名
* @return
*/
public static Object mockData(String dateType, String proertyName) {
Class dateTypeClazz = EnhanceClassUtil.getJdkClass(dateType);
if (dateTypeClazz != null) {
// 不支持容器类型转换
if (Collection.class.isAssignableFrom(dateTypeClazz)) {
return Collections.emptyList();
} else {
return mockRandomData(dateType);
}
} else {
return null;
}
}
public static void main(String[] args) {
MethodLoader methodLoader = Mock.mockMethodLoader();
methodLoader.append(ReflectUtil.getMethod(EnhanceMockUtil.class, "testMock"));
methodLoader.append(ReflectUtil.getMethod(EnhanceMockUtil.class, "mockData", String.class, String.class));
methodLoader.load();
Map<String, Object> ruleMap = new HashMap<>();
ruleMap.put("age1", "@age");
ruleMap.put("age2", 15);
ruleMap.put("age3", new Integer[]{1, 2, 3, 4});
ruleMap.put("name1", "@name");
ruleMap.put("name2", "@title(2)");
ruleMap.put("name3", "这是一个名字");
ruleMap.put("email1", "@email('这是中文')");
ruleMap.put("email2", "@email('this is english')");
ruleMap.put("email3", "@email(this is english)");
ruleMap.put("testMock", "@testMock");
ruleMap.put("mockData", "@mockData('fdsfds','fdsfdsf5345')");
// ruleMap.put("email4" , null);
MockMapBean test = Mock.setResult("test", ruleMap, false);
test.getObject().entrySet()
.forEach(Console::log);
}
}
MyMockUtil.java
package work.linruchang.lrcutilsweb.util;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.forte.util.Mock;
import com.forte.util.loader.MethodLoader;
import com.forte.util.mockbean.MockMapBean;
import java.util.HashMap;
import java.util.Map;
/**
* @author LinRuChang
* @version 1.0
* @date 2022/10/08
* @since 1.8
**/
public class MyMockUtil {
static {
MethodLoader methodLoader = Mock.mockMethodLoader();
methodLoader.append(ReflectUtil.getMethod(EnhanceMockUtil.class, "mockData", String.class, String.class));
methodLoader.load();
}
public static Map<String,Object> mockResult(Map<String, Object> ruleMap) {
MockMapBean test = Mock.setResult(UUID.fastUUID().toString(true), ruleMap, false);
return test.getObject();
}
public static String mockResultJson(Map<String, Object> ruleMap) {
return JSONUtil.toJsonStr(mockResult(ruleMap));
}
public static Map<String, Object> generateRuleMap(Map<String, Object> beanFieldStructure) {
HashMap<String, Object> copyMap = MapUtil.newHashMap();
BeanUtil.copyProperties(beanFieldStructure, copyMap);
return generateRuleMapByLoop(copyMap);
}
/**
* 基于结构生成mock规则
*
* @param beanFieldStructure Bean结构
* @return
*/
private static Map<String, Object> generateRuleMapByLoop(Map<String, Object> beanFieldStructure) {
MapUtil.emptyIfNull(beanFieldStructure).forEach((properName, properType) -> {
if(properType != null) {
if(properType instanceof Class) {
beanFieldStructure.put(properName, StrUtil.format("@mockData('{}','{}')", ((Class<?>) properType).getName(), properName));
}else {
generateRuleMapByLoop((Map<String, Object>) properType);
}
}else {
beanFieldStructure.put(properName, StrUtil.format("@mockData('{}','{}')", null, properName));
}
});
return beanFieldStructure;
}
}
测试
@Test
public void testGenerateRuleMap3() {
Map<String,Object> map = new HashMap<>();
map.put("name", "@name");
Map<String,Object> infoMap = new HashMap<>();
infoMap.put("year", "@UUNUM");
map.put("info", infoMap);
map.put("aa", "@mockData('long','aa')");
map.put("bb", StrUtil.format("@mockData('{}','{}')", String[].class.getName(),"bb"));
String s = MyMockUtil.mockResultJson(map);
Console.log(JSONUtil.formatJsonStr(s));
}