【8.3.0】【scanner】从新整理class类型解析

pull/62/head
stylefeng 2024-08-07 13:03:36 +08:00
parent 3de0006f63
commit 97c18870d3
12 changed files with 484 additions and 518 deletions

View File

@ -1,9 +1,7 @@
package cn.stylefeng.roses.kernel.rule.pojo.clazz;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.lang.reflect.Type;
@ -14,8 +12,6 @@ import java.lang.reflect.Type;
* @since 2024/8/6 21:49
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClassParseResult {
/**
@ -33,4 +29,23 @@ public class ClassParseResult {
*/
private Type genericType;
/**
* FieldTypeEnum = FieldTypeEnum.OBJECT_WITH_GENERIC class
*/
private Class<?> rawTypeClass;
public ClassParseResult() {
}
public ClassParseResult(FieldTypeEnum fieldTypeEnum, Type genericType) {
this.fieldTypeEnum = fieldTypeEnum;
this.genericType = genericType;
}
public ClassParseResult(FieldTypeEnum fieldTypeEnum, Type genericType, Class<?> rawTypeClass) {
this.fieldTypeEnum = fieldTypeEnum;
this.genericType = genericType;
this.rawTypeClass = rawTypeClass;
}
}

View File

@ -2,11 +2,10 @@ package cn.stylefeng.roses.kernel.scanner.api.context;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.rule.pojo.clazz.ClassParseResult;
import cn.stylefeng.roses.kernel.scanner.api.enums.ParamTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.util.AdvancedClassTypeUtil;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@ -68,32 +67,20 @@ public class MetadataContext {
/**
*
*
* @return true-false-
* @author fengshuonan
* @since 2022/1/15 10:50
*/
public static boolean ensureFieldClassHaveParse(String uuid, Type genericType) {
public static boolean ensureFieldClassHaveParse(String uuid, Class<?> genericType) {
Set<String> classRecords = META_DATA_CLASS_COUNT_CONTEXT.get(uuid);
if (classRecords != null) {
// 获取字段类型如果是数组collection带实体的需要获取真实的实体类型
FieldTypeEnum classFieldType = AdvancedClassTypeUtil.getClassFieldType(genericType);
ClassParseResult classParseResult = AdvancedClassTypeUtil.getClassFieldType(genericType);
FieldTypeEnum classFieldType = classParseResult.getFieldTypeEnum();
// 如果是对象类型,直接判断
if (classFieldType.equals(FieldTypeEnum.OBJECT)) {
return classRecords.contains(((Class<?>) genericType).getName());
}
// 数组类型,则获取数组的实体
if (classFieldType.equals(FieldTypeEnum.ARRAY_WITH_OBJECT)) {
Class<?> originClass = (Class<?>) genericType;
return classRecords.contains(originClass.getComponentType().getName());
}
// 集合类型,获取集合的真实类型
if (classFieldType.equals(FieldTypeEnum.COLLECTION_WITH_OBJECT)) {
// 获取泛型
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
return ensureFieldClassHaveParse(uuid, actualTypeArgument);
return classRecords.contains(genericType.getName());
}
}
return false;

View File

@ -0,0 +1,48 @@
package cn.stylefeng.roses.kernel.scanner.api.factory;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import cn.stylefeng.roses.kernel.scanner.api.util.ClassReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
*
*
* @author fengshuonan
* @since 2024/8/7 10:38
*/
public class AnnotationParseFactory {
/**
*
*
* @author fengshuonan
* @since 2022/1/14 11:57
*/
public static void parsingAnnotation(Field declaredField, FieldMetadata fieldDescription) {
Annotation[] annotations = declaredField.getAnnotations();
if (annotations != null && annotations.length > 0) {
// 设置字段的所有注解
fieldDescription.setAnnotations(ClassReflectUtil.annotationsToStrings(annotations));
// 遍历字段上的所有注解找到带groups属性的按group分类组装注解
Map<String, Set<String>> groupAnnotations = new HashMap<>();
for (Annotation annotation : annotations) {
Class<?>[] validateGroupsClasses = ClassReflectUtil.invokeAnnotationMethodIgnoreError(annotation, "groups", Class[].class);
if (validateGroupsClasses != null) {
for (Class<?> validateGroupsClass : validateGroupsClasses) {
ClassReflectUtil.addGroupValidateAnnotation(annotation, validateGroupsClass, groupAnnotations);
}
}
}
// 设置分组注解
fieldDescription.setGroupValidationMessage(groupAnnotations);
}
}
}

View File

@ -1,189 +0,0 @@
package cn.stylefeng.roses.kernel.scanner.api.factory;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.constants.ScannerConstants;
import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import cn.stylefeng.roses.kernel.scanner.api.util.AdvancedClassTypeUtil;
import cn.stylefeng.roses.kernel.scanner.api.util.ClassDescriptionUtil;
import cn.stylefeng.roses.kernel.scanner.api.util.FieldDescriptionUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedHashSet;
import java.util.Set;
/**
*
*
* @author fengshuonan
* @since 2022/1/13 13:49
*/
@Slf4j
public class ClassDetailMetadataFactory {
/**
*
*
* @param fieldType class
* @param uuid context
* @author fengshuonan
* @since 2022/1/14 14:31
*/
public static Set<FieldMetadata> createFieldDetailMetadataSet(Type fieldType, String uuid) {
// 获取参数的类型枚举
FieldTypeEnum classFieldType = AdvancedClassTypeUtil.getClassFieldType(fieldType);
// 设置响应结果
Set<FieldMetadata> fieldMetadata = null;
// 根据字段类型的不同进行响应的处理
switch (classFieldType) {
case BASIC:
// 基本类型不需要填充子类型信息
fieldMetadata = null;
break;
case BASE_ARRAY:
// 如果是简单数组类型,则描述一下这个基本类型的信息
Class<?> baseArrayFieldClazz = (Class<?>) fieldType;
Class<?> baseArrayComponentType = baseArrayFieldClazz.getComponentType();
FieldMetadata baseMetadata = ClassDescriptionUtil.createClassMetadata(baseArrayComponentType, FieldTypeEnum.BASIC, uuid);
fieldMetadata = new LinkedHashSet<>();
fieldMetadata.add(baseMetadata);
break;
case ARRAY_WITH_OBJECT:
// 如果是带实体的数组,则加上实体对应的字段信息
Class<?> objArrayClass = (Class<?>) fieldType;
Class<?> objArrayComponentType = objArrayClass.getComponentType();
fieldMetadata = ClassDetailMetadataFactory.createFieldDetailMetadataSet(objArrayComponentType, uuid);
break;
case BASE_COLLECTION:
// 如果是基础集合因为不确定集合的内容所以使用Object来描述一下集合的具体内容
FieldMetadata collectionFieldMetadata = ClassDescriptionUtil.createClassMetadata(Object.class, FieldTypeEnum.OBJECT, uuid);
fieldMetadata = new LinkedHashSet<>();
fieldMetadata.add(collectionFieldMetadata);
break;
case COLLECTION_WITH_OBJECT:
// 如果是集合里带的具体实体对象,则描述一下具体实体的数据结构
ParameterizedType collectionParameterizedType = (ParameterizedType) fieldType;
Type[] actualTypeArguments = collectionParameterizedType.getActualTypeArguments();
fieldMetadata = ClassDetailMetadataFactory.createFieldDetailMetadataSet(actualTypeArguments[0], uuid);
break;
case OBJECT:
// 如果是实体对象,则描述实体对象的所有字段信息
Class<?> objectClass = (Class<?>) fieldType;
fieldMetadata = new LinkedHashSet<>();
processClassFields(objectClass, fieldMetadata, uuid);
break;
case OBJECT_WITH_GENERIC:
// 如果是带泛型的Object实体类型
ParameterizedType objWithGenericParameterizedType = (ParameterizedType) fieldType;
// 先获取主体类型
Type rawType = objWithGenericParameterizedType.getRawType();
// 获取具体泛型
Type genericType = objWithGenericParameterizedType.getActualTypeArguments()[0];
// 判断带泛型的实体,有没有进行做字段解析,如果解析过,则跳过
String totalName = fieldType.getTypeName() + genericType.getTypeName();
if (MetadataContext.ensureFieldClassHaveParse(uuid, totalName)) {
return null;
}
MetadataContext.addClassRecord(uuid, totalName);
// 获取主体的所有字段信息
fieldMetadata = getEntityWithGenericFieldMetadataList(rawType, genericType, uuid);
default:
}
return fieldMetadata;
}
/**
* PageResult<SysUser>
*
* @author fengshuonan
* @since 2022/1/14 18:51
*/
public static Set<FieldMetadata> getEntityWithGenericFieldMetadataList(Type fieldType, Type genericType, String uuid) {
if (fieldType instanceof Class<?>) {
Class<?> clazz = (Class<?>) fieldType;
// 获取主类型的所有属性
Set<FieldMetadata> fieldDetailMetadataSet = createFieldDetailMetadataSet(clazz, uuid);
if (fieldDetailMetadataSet == null) {
return null;
}
for (FieldMetadata fieldMetadata : fieldDetailMetadataSet) {
// 如果是带泛型集合如下情况List<T>,又或是直接 T 这种形式
if (FieldTypeEnum.COLLECTION_WITH_OBJECT.getCode().equals(fieldMetadata.getFieldType())
|| FieldTypeEnum.WITH_UNKNOWN_GENERIC.getCode().equals(fieldMetadata.getFieldType())) {
// 设置这个字段的子字段描述
fieldMetadata.setGenericFieldMetadata(createFieldDetailMetadataSet(genericType, uuid));
}
// 如果T在携带在一个实体类上例如ResponseData<T>这种形式
else if (FieldTypeEnum.OBJECT_WITH_GENERIC.getCode().equals(fieldMetadata.getFieldType())) {
// 设置这个字段的子字段描述
Set<FieldMetadata> current = null;
try {
current = getEntityWithGenericFieldMetadataList(Class.forName(fieldMetadata.getFieldClassPath()), genericType, uuid);
} catch (ClassNotFoundException e) {
log.error("类无法找到" + fieldMetadata.getFieldClassPath(), e);
continue;
}
fieldMetadata.setGenericFieldMetadata(current);
}
// 如果是T这种形式应该将当前fieldMetadata的类型改为泛型的类型例如参数genericType是List时候
if (FieldTypeEnum.WITH_UNKNOWN_GENERIC.getCode().equals(fieldMetadata.getFieldType())) {
FieldTypeEnum classFieldType = AdvancedClassTypeUtil.getClassFieldType(genericType);
fieldMetadata.setFieldType(classFieldType.getCode());
}
}
return fieldDetailMetadataSet;
} else {
log.debug("带泛型的实体主题rawType非Class类型" + fieldType);
return null;
}
}
/**
*
*
* @author fengshuonan
* @since 2022/1/14 18:51
*/
private static void processClassFields(Class<?> clazz, Set<FieldMetadata> fieldMetadata, String uuid) {
if (clazz == null || clazz == Object.class) {
return;
}
// 在处理Object中所有字段之前将当前父类放进context所有子字段不能含有父类的类型否则会递归
MetadataContext.addClassRecord(uuid, clazz.getName());
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
FieldMetadata fieldInfo;
// 判断字段是否是基础字段例如serialVersionUID或者delFlag等字段
if (ScannerConstants.DONT_PARSE_FIELD.contains(field.getName())) {
continue;
}
// 判断该实体是否被解析过,防止无限递归解析实体
if (MetadataContext.ensureFieldClassHaveParse(uuid, field.getGenericType())) {
fieldInfo = FieldDescriptionUtil.createBasicMetadata(field, uuid);
} else {
fieldInfo = FieldDescriptionUtil.createFieldMetadata(field, uuid);
}
fieldMetadata.add(fieldInfo);
}
// 递归处理父类
processClassFields(clazz.getSuperclass(), fieldMetadata, uuid);
}
}

View File

@ -0,0 +1,202 @@
package cn.stylefeng.roses.kernel.scanner.api.factory;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.rule.pojo.clazz.ClassParseResult;
import cn.stylefeng.roses.kernel.scanner.api.constants.ScannerConstants;
import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.SubFieldMetadataDTO;
import cn.stylefeng.roses.kernel.scanner.api.util.AdvancedClassTypeUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.LinkedHashSet;
import java.util.Set;
/**
*
*
* @author fengshuonan
* @since 2022/1/13 13:49
*/
@Slf4j
public class ClassMetaFactory {
/**
* ClassParameterizedType
*
* @param type class
* @param uuid context
* @return
* @author fengshuonan
* @since 2022/1/13 13:51
*/
public static FieldMetadata beginCreateFieldMetadata(Type type, String uuid) {
// 获取类型的枚举
ClassParseResult classParseResult = AdvancedClassTypeUtil.getClassFieldType(type);
// 1. 如果是基础类型,直接渲染结果
if (FieldTypeEnum.BASIC.equals(classParseResult.getFieldTypeEnum())) {
return MetadataCreateFactory.createBaseClassMetadata((Class<?>) type, uuid);
}
// 2. 如果是数组类型,则先创建一个数组类型的元数据,再获取数组具体的类型,再继续解析数组的类型
else if (FieldTypeEnum.ARRAY.equals(classParseResult.getFieldTypeEnum())) {
return createArrayMetaDateResult(uuid, classParseResult);
}
// 3. 如果是collection集合类型同array类型
else if (FieldTypeEnum.COLLECTION.equals(classParseResult.getFieldTypeEnum())) {
return createArrayMetaDateResult(uuid, classParseResult);
}
// 4. 如果是Object类型则找到对象的所有的子字段填充到genericFieldMetadata这个字段中
else if (FieldTypeEnum.OBJECT.equals(classParseResult.getFieldTypeEnum())) {
// 获取对象的类信息
Class<?> clazz = (Class<?>) type;
// 创建对象的基础信息
FieldMetadata currentClassMetaData = MetadataCreateFactory.createBaseClassMetadata((Class<?>) type, uuid);
// 如果被初始化过,则不继续进行解析
if (MetadataContext.ensureFieldClassHaveParse(uuid, clazz)) {
return currentClassMetaData;
}
// 获取对象的所有字段信息,这里因为要递归获取本类+父类的字段,所以先创建空集合
Set<FieldMetadata> totalFieldList = new LinkedHashSet<>();
ClassMetaFactory.processClassFields(clazz, totalFieldList, uuid);
currentClassMetaData.setGenericFieldMetadata(totalFieldList);
return currentClassMetaData;
}
// 5. 如果是携带泛型的对象
else if (FieldTypeEnum.OBJECT_WITH_GENERIC.equals(classParseResult.getFieldTypeEnum())) {
// 先解析主体的字段信息
Class<?> rawTypeClass = classParseResult.getRawTypeClass();
// 解析主体字段的所有信息
FieldMetadata rawTypeMetadata = ClassMetaFactory.beginCreateFieldMetadata(rawTypeClass, uuid);
// **这里需要遍历一下所有字段如果有T类型则需要单独配置一下T类型的FieldMetadata**
// 1. 遍历所有字段
Set<FieldMetadata> genericFieldMetadata = rawTypeMetadata.getGenericFieldMetadata();
if (ObjectUtil.isEmpty(genericFieldMetadata)) {
return rawTypeMetadata;
}
for (FieldMetadata subField : genericFieldMetadata) {
if (!FieldTypeEnum.WITH_UNKNOWN_GENERIC.getCode().equals(subField.getFieldType())) {
continue;
}
// 2. 获取这个字段的类型,也就是泛型对象的泛型
Type subFieldType = classParseResult.getGenericType();
// 3. 继续进行这个字段的解析,判断是否需要填充子字段或者数组字段
SubFieldMetadataDTO typeSubInfo = ClassMetaFactory.getTypeSubInfo(uuid, subFieldType);
subField.setGenericFieldMetadata(typeSubInfo.getGenericFieldMetadata());
subField.setArrayFieldMetadata(typeSubInfo.getArrayFieldMetadata());
}
return rawTypeMetadata;
}
// 6. 其他情况,返回最基本的数据
else {
return MetadataCreateFactory.createBaseClassMetadata((Class<?>) type, uuid);
}
}
/**
*
*
* @author fengshuonan
* @since 2024/8/7 10:05
*/
private static FieldMetadata createArrayMetaDateResult(String uuid, ClassParseResult classParseResult) {
// 先创建一个数组类型的元数据
FieldMetadata arrayItemMetadata = MetadataCreateFactory.createArrayItemMetadata(uuid);
// 获取数组元素的类型
Type genericType = classParseResult.getGenericType();
// 再将数组的类型进行解析,(递归调用)
FieldMetadata arrayFieldMetadata = ClassMetaFactory.beginCreateFieldMetadata(genericType, uuid);
arrayItemMetadata.setArrayFieldMetadata(arrayFieldMetadata);
return arrayItemMetadata;
}
/**
*
*
* @author fengshuonan
* @since 2024/8/7 10:15
*/
private static void processClassFields(Class<?> clazz, Set<FieldMetadata> fieldMetadata, String uuid) {
if (clazz == null || Object.class.equals(clazz)) {
return;
}
// 在处理Object中所有字段之前将当前父类放进context所有子字段不能含有父类的类型否则会递归
MetadataContext.addClassRecord(uuid, clazz.getName());
// 获取类中的所有字段
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 1. 判断字段是否是基础字段例如serialVersionUID或者delFlag等字段
if (ScannerConstants.DONT_PARSE_FIELD.contains(field.getName())) {
continue;
}
// 2. 先填充这个字段的基础信息
FieldMetadata fieldInfo = MetadataCreateFactory.createBaseFieldMetadata(field, uuid);
// 3. 再根据这个字段的类型,进行递归解析子属性的填充
Type genericType = field.getGenericType();
SubFieldMetadataDTO typeSubInfo = ClassMetaFactory.getTypeSubInfo(uuid, genericType);
fieldInfo.setGenericFieldMetadata(typeSubInfo.getGenericFieldMetadata());
fieldInfo.setArrayFieldMetadata(typeSubInfo.getArrayFieldMetadata());
fieldMetadata.add(fieldInfo);
}
// 递归处理父类
processClassFields(clazz.getSuperclass(), fieldMetadata, uuid);
}
/**
* Type
* <p>
* obj
*
* @author fengshuonan
* @since 2024/8/7 11:43
*/
public static SubFieldMetadataDTO getTypeSubInfo(String uuid, Type type) {
SubFieldMetadataDTO fieldInfo = new SubFieldMetadataDTO();
// 1. 获取这个对应type的类型信息
FieldMetadata validateFieldHaveSubInfo = ClassMetaFactory.beginCreateFieldMetadata(type, uuid);
// 2. 填充他的子对象用来针对obj类型的字段进行解析
Set<FieldMetadata> genericFieldMetadata = validateFieldHaveSubInfo.getGenericFieldMetadata();
if (ObjectUtil.isNotEmpty(genericFieldMetadata)) {
fieldInfo.setGenericFieldMetadata(genericFieldMetadata);
}
// 3. 填充他的数组对象用来针对array类型的字段进行解析
FieldMetadata arrayFieldMetadata = validateFieldHaveSubInfo.getArrayFieldMetadata();
if (ObjectUtil.isNotEmpty(arrayFieldMetadata)) {
fieldInfo.setArrayFieldMetadata(arrayFieldMetadata);
}
return fieldInfo;
}
}

View File

@ -1,71 +0,0 @@
package cn.stylefeng.roses.kernel.scanner.api.factory;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import cn.stylefeng.roses.kernel.scanner.api.util.AdvancedClassTypeUtil;
import cn.stylefeng.roses.kernel.scanner.api.util.ClassDescriptionUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Set;
/**
*
*
* @author fengshuonan
* @since 2022/1/13 13:49
*/
@Slf4j
public class ClassMetadataFactory {
/**
* ClassParameterizedType
*
* @param type class
* @param uuid context
* @return
* @author fengshuonan
* @since 2022/1/13 13:51
*/
public static FieldMetadata beginCreateFieldMetadata(Type type, String uuid) {
// 获取类型的枚举
FieldTypeEnum classFieldType = AdvancedClassTypeUtil.getClassFieldType(type);
// 设置响应结果
FieldMetadata fieldMetadata = null;
// 组装类的基本信息
if (type instanceof Class<?>) {
Class<?> clazz = (Class<?>) type;
// 创建类型的基本信息
fieldMetadata = ClassDescriptionUtil.createClassMetadata(clazz, classFieldType, uuid);
// 补充类型的子信息
Set<FieldMetadata> fieldDetailMetadataSet = ClassDetailMetadataFactory.createFieldDetailMetadataSet(clazz, uuid);
fieldMetadata.setGenericFieldMetadata(fieldDetailMetadataSet);
}
// 如果是带泛型的
else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
// 创建类型的基本信息
fieldMetadata = ClassDescriptionUtil.createParameterizedMetadata(parameterizedType, classFieldType, uuid);
// 补充类型的子信息
Set<FieldMetadata> fieldDetailMetadataSet = ClassDetailMetadataFactory.createFieldDetailMetadataSet(type, uuid);
fieldMetadata.setGenericFieldMetadata(fieldDetailMetadataSet);
}
// 其他情况
else {
log.debug("未知类型的处理既不是class也不是ParameterizedType打印出类的信息如下{}", type.getTypeName());
}
return fieldMetadata;
}
}

View File

@ -0,0 +1,152 @@
package cn.stylefeng.roses.kernel.scanner.api.factory;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.rule.annotation.ChineseDescription;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.rule.pojo.clazz.ClassParseResult;
import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext;
import cn.stylefeng.roses.kernel.scanner.api.enums.ParamTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import cn.stylefeng.roses.kernel.scanner.api.util.AdvancedClassTypeUtil;
import java.lang.reflect.Field;
/**
*
*
* @author fengshuonan
* @since 2024/8/7 9:49
*/
public class MetadataCreateFactory {
/**
* metadata
* <p>
* fieldTypeEnum使
*
* @author fengshuonan
* @since 2024/8/7 9:48
*/
public static FieldMetadata createBaseClassMetadata(Class<?> clazz, String uuid) {
FieldMetadata fieldMetadataItem = new FieldMetadata();
// 设置唯一id
fieldMetadataItem.setMetadataId(IdUtil.fastSimpleUUID());
// 设置字段中文含义
fieldMetadataItem.setChineseName(clazz.getSimpleName());
// 设置字段类类型
fieldMetadataItem.setFieldClassType(clazz.getSimpleName());
// 设置类的全路径
fieldMetadataItem.setFieldClassPath(clazz.getName());
// 根据uuid获取参数的名称
String paramName = MetadataContext.getParamName(uuid);
if (StrUtil.isNotBlank(paramName)) {
fieldMetadataItem.setFieldName(paramName);
}
// 设置字段类型,基本类型
fieldMetadataItem.setFieldType(FieldTypeEnum.BASIC.getCode());
// 设置当前context构造的参数类型
ParamTypeEnum paramTypeMetadata = MetadataContext.getParamTypeMetadata(uuid);
if (paramTypeMetadata != null) {
fieldMetadataItem.setRequestParamType(paramTypeMetadata.getCode());
}
// 设置字段
return fieldMetadataItem;
}
/**
*
*
* @author fengshuonan
* @since 2024/8/7 9:53
*/
public static FieldMetadata createArrayItemMetadata(String uuid) {
FieldMetadata fieldMetadataItem = new FieldMetadata();
// 设置唯一id
fieldMetadataItem.setMetadataId(IdUtil.fastSimpleUUID());
// 设置字段中文含义
fieldMetadataItem.setChineseName("数组元素");
// 设置字段类类型
fieldMetadataItem.setFieldClassType("String");
// 设置类的全路径
fieldMetadataItem.setFieldClassPath("java.lang.String");
// 设置字段名称
fieldMetadataItem.setFieldName("arrayItem");
// 根据uuid获取参数的名称
String paramName = MetadataContext.getParamName(uuid);
if (StrUtil.isNotBlank(paramName)) {
fieldMetadataItem.setFieldName(paramName);
}
// 设置数组类型
fieldMetadataItem.setFieldType(FieldTypeEnum.ARRAY.getCode());
// 设置当前context构造的参数类型
ParamTypeEnum paramTypeMetadata = MetadataContext.getParamTypeMetadata(uuid);
if (paramTypeMetadata != null) {
fieldMetadataItem.setRequestParamType(paramTypeMetadata.getCode());
}
// 设置字段
return fieldMetadataItem;
}
/**
*
*
* @author fengshuonan
* @since 2024/8/7 10:36
*/
public static FieldMetadata createBaseFieldMetadata(Field field, String uuid) {
FieldMetadata fieldMetadataItem = new FieldMetadata();
// 设置唯一id
fieldMetadataItem.setMetadataId(IdUtil.fastSimpleUUID());
// 设置字段中文含义
ChineseDescription annotation = field.getAnnotation(ChineseDescription.class);
if (annotation != null) {
fieldMetadataItem.setChineseName(annotation.value());
}
// 设置字段类类型
Class<?> classType = field.getType();
fieldMetadataItem.setFieldClassType(classType.getSimpleName());
// 设置类的全路径
fieldMetadataItem.setFieldClassPath(classType.getName());
// 设置对应字段名称
fieldMetadataItem.setFieldName(field.getName());
// 处理注解信息
AnnotationParseFactory.parsingAnnotation(field, fieldMetadataItem);
// 设置字段类型基本、数组、还是object
ClassParseResult classParseResult = AdvancedClassTypeUtil.getClassFieldType(field.getGenericType());
fieldMetadataItem.setFieldType(classParseResult.getFieldTypeEnum().getCode());
// 设置当前context构造的参数类型
ParamTypeEnum paramTypeMetadata = MetadataContext.getParamTypeMetadata(uuid);
if (paramTypeMetadata != null) {
fieldMetadataItem.setRequestParamType(paramTypeMetadata.getCode());
}
return fieldMetadataItem;
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright [2020-2030] [https://www.stylefeng.cn]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* GunsAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Guns
* 3.
* 4. https://gitee.com/stylefeng/guns
* 5. https://gitee.com/stylefeng/guns
* 6.
*/
package cn.stylefeng.roses.kernel.scanner.api.pojo.resource;
import cn.stylefeng.roses.kernel.rule.annotation.ChineseDescription;
import lombok.Data;
import java.util.Set;
/**
* obj
*
* @author fengshuonan
* @since 2024/8/7 11:41
*/
@Data
public class SubFieldMetadataDTO {
/**
* object
*/
@ChineseDescription("泛型或object类型的字段的描述")
private Set<FieldMetadata> genericFieldMetadata;
/**
*
*/
@ChineseDescription("针对数组类型的字段,指定数组的子类型")
private FieldMetadata arrayFieldMetadata;
}

View File

@ -137,7 +137,7 @@ public class AdvancedClassTypeUtil {
// 如果泛型的主体是实体包装类
else if (AdvancedClassTypeUtil.ensureEntityFlag(rawTypeClass)) {
return new ClassParseResult(FieldTypeEnum.OBJECT_WITH_GENERIC, actualTypeArgument);
return new ClassParseResult(FieldTypeEnum.OBJECT_WITH_GENERIC, actualTypeArgument, rawTypeClass);
}
// 泛型的主体情况不确定,不处理

View File

@ -1,114 +0,0 @@
package cn.stylefeng.roses.kernel.scanner.api.util;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext;
import cn.stylefeng.roses.kernel.scanner.api.enums.GenericFieldMetadataType;
import cn.stylefeng.roses.kernel.scanner.api.enums.ParamTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
*
*
* @author fengshuonan
* @since 2022/1/14 10:59
*/
public class ClassDescriptionUtil {
/**
*
*
* @author fengshuonan
* @since 2022/1/13 18:06
*/
public static FieldMetadata createClassMetadata(Class<?> clazz, FieldTypeEnum fieldTypeEnum, String uuid) {
FieldMetadata fieldMetadataItem = new FieldMetadata();
// 设置唯一id
fieldMetadataItem.setMetadataId(IdUtil.fastSimpleUUID());
// 设置字段中文含义
fieldMetadataItem.setChineseName(clazz.getSimpleName());
// 设置字段类类型
fieldMetadataItem.setFieldClassType(clazz.getSimpleName());
// 设置类的全路径
fieldMetadataItem.setFieldClassPath(clazz.getName());
// 根据uuid获取参数的名称
String paramName = MetadataContext.getParamName(uuid);
if (StrUtil.isNotBlank(paramName)) {
fieldMetadataItem.setFieldName(paramName);
}
// 【2024年8月5日新增】判断数组的类型
fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.BASE_TYPE.getCode());
if (FieldTypeEnum.ARRAY_WITH_OBJECT.equals(fieldTypeEnum)) {
fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.OBJECT_TYPE.getCode());
}
// 如果是集合类型,判断集合的泛型,集合的泛型是对象的话,就是对象类型,否则就是基本类型
else if (FieldTypeEnum.COLLECTION_WITH_OBJECT.equals(fieldTypeEnum)) {
if (ClassDescriptionUtil.getClassGenObjectFlag(clazz)) {
fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.OBJECT_TYPE.getCode());
}
}
// 设置字段类型基本、数组、还是object
fieldMetadataItem.setFieldType(fieldTypeEnum.getCode());
// 设置当前context构造的参数类型
ParamTypeEnum paramTypeMetadata = MetadataContext.getParamTypeMetadata(uuid);
if (paramTypeMetadata != null) {
fieldMetadataItem.setRequestParamType(paramTypeMetadata.getCode());
}
// 设置字段
return fieldMetadataItem;
}
/**
*
*
* @author fengshuonan
* @since 2022/1/13 18:06
*/
public static FieldMetadata createParameterizedMetadata(ParameterizedType parameterizedType, FieldTypeEnum fieldTypeEnum, String uuid) {
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
FieldMetadata classMetadata = createClassMetadata(rawType, fieldTypeEnum, uuid);
// 设置泛型的类型
boolean classGenObjectFlag = ClassDescriptionUtil.getClassGenObjectFlag(parameterizedType);
if (classGenObjectFlag) {
classMetadata.setGenericFieldMetadataType(GenericFieldMetadataType.OBJECT_TYPE.getCode());
}
return classMetadata;
}
/**
* Object
*
* @author fengshuonan
* @since 2024/8/5 14:36
*/
public static boolean getClassGenObjectFlag(Class<?> clazz) {
Type genericSuperclass = clazz.getGenericSuperclass();
return getClassGenObjectFlag(genericSuperclass);
}
/**
* Object
*
* @author fengshuonan
* @since 2024/8/5 14:36
*/
public static boolean getClassGenObjectFlag(Type type) {
if (type instanceof ParameterizedType parameterizedType) {
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 0) {
Type actualTypeArgument = actualTypeArguments[0];
FieldTypeEnum classFieldType = AdvancedClassTypeUtil.getClassFieldType(actualTypeArgument);
return FieldTypeEnum.OBJECT.equals(classFieldType);
}
}
return false;
}
}

View File

@ -1,117 +0,0 @@
package cn.stylefeng.roses.kernel.scanner.api.util;
import cn.hutool.core.util.IdUtil;
import cn.stylefeng.roses.kernel.rule.annotation.ChineseDescription;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext;
import cn.stylefeng.roses.kernel.scanner.api.enums.GenericFieldMetadataType;
import cn.stylefeng.roses.kernel.scanner.api.enums.ParamTypeEnum;
import cn.stylefeng.roses.kernel.scanner.api.factory.ClassDetailMetadataFactory;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
*
*
* @author fengshuonan
* @since 2022/1/14 10:59
*/
public class FieldDescriptionUtil {
/**
*
*
* @author fengshuonan
* @since 2022/1/13 18:06
*/
public static FieldMetadata createBasicMetadata(Field field, String uuid) {
FieldMetadata fieldMetadataItem = new FieldMetadata();
// 设置唯一id
fieldMetadataItem.setMetadataId(IdUtil.fastSimpleUUID());
// 设置字段中文含义
ChineseDescription annotation = field.getAnnotation(ChineseDescription.class);
if (annotation != null) {
fieldMetadataItem.setChineseName(annotation.value());
}
// 设置字段类类型
Class<?> classType = field.getType();
fieldMetadataItem.setFieldClassType(classType.getSimpleName());
// 设置类的全路径
fieldMetadataItem.setFieldClassPath(classType.getName());
// 设置对应字段名称
fieldMetadataItem.setFieldName(field.getName());
// 处理注解信息
parsingAnnotation(field, fieldMetadataItem);
// 设置是否带泛型
Type genericType = field.getGenericType();
// 【2024年8月5日新增】更新判断泛型的对象类型的方法
boolean classGenObjectFlag = ClassDescriptionUtil.getClassGenObjectFlag(genericType);
if (classGenObjectFlag) {
fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.OBJECT_TYPE.getCode());
} else {
fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.BASE_TYPE.getCode());
}
// 设置字段类型基本、数组、还是object
FieldTypeEnum classFieldType = AdvancedClassTypeUtil.getClassFieldType(genericType);
fieldMetadataItem.setFieldType(classFieldType.getCode());
// 设置当前context构造的参数类型
ParamTypeEnum paramTypeMetadata = MetadataContext.getParamTypeMetadata(uuid);
if (paramTypeMetadata != null) {
fieldMetadataItem.setRequestParamType(paramTypeMetadata.getCode());
}
return fieldMetadataItem;
}
/**
* +
* <p>
*
*
* @author fengshuonan
* @since 2022/1/13 18:06
*/
public static FieldMetadata createFieldMetadata(Field field, String uuid) {
// 先组装基础数据
FieldMetadata fieldMetadata = createBasicMetadata(field, uuid);
// 组装子类型数据
Type genericType = field.getGenericType();
Set<FieldMetadata> fieldDetailMetadataSet = ClassDetailMetadataFactory.createFieldDetailMetadataSet(genericType, uuid);
fieldMetadata.setGenericFieldMetadata(fieldDetailMetadataSet);
return fieldMetadata;
}
/**
*
*
* @author fengshuonan
* @since 2022/1/14 11:57
*/
private static void parsingAnnotation(Field declaredField, FieldMetadata fieldDescription) {
Annotation[] annotations = declaredField.getAnnotations();
if (annotations != null && annotations.length > 0) {
// 设置字段的所有注解
fieldDescription.setAnnotations(ClassReflectUtil.annotationsToStrings(annotations));
// 遍历字段上的所有注解找到带groups属性的按group分类组装注解
Map<String, Set<String>> groupAnnotations = new HashMap<>();
for (Annotation annotation : annotations) {
Class<?>[] validateGroupsClasses = ClassReflectUtil.invokeAnnotationMethodIgnoreError(annotation, "groups", Class[].class);
if (validateGroupsClasses != null) {
for (Class<?> validateGroupsClass : validateGroupsClasses) {
ClassReflectUtil.addGroupValidateAnnotation(annotation, validateGroupsClass, groupAnnotations);
}
}
}
// 设置分组注解
fieldDescription.setGroupValidationMessage(groupAnnotations);
}
}
}

View File

@ -38,7 +38,7 @@ import cn.stylefeng.roses.kernel.scanner.api.annotation.PostResource;
import cn.stylefeng.roses.kernel.scanner.api.constants.ScannerConstants;
import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext;
import cn.stylefeng.roses.kernel.scanner.api.exception.ScannerException;
import cn.stylefeng.roses.kernel.scanner.api.factory.ClassMetadataFactory;
import cn.stylefeng.roses.kernel.scanner.api.factory.ClassMetaFactory;
import cn.stylefeng.roses.kernel.scanner.api.holder.IpAddrHolder;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.ParameterMetadata;
@ -312,7 +312,7 @@ public class ApiResourceScanner implements BeanPostProcessor {
// 填充方法返回结果字段的详细信息
Type returnType = MethodReflectUtil.getMethodReturnType(method);
String processReturnTypeUuid = RandomUtil.randomString(32);
resourceDefinition.setResponseFieldDescriptions(ClassMetadataFactory.beginCreateFieldMetadata(returnType, processReturnTypeUuid));
resourceDefinition.setResponseFieldDescriptions(ClassMetaFactory.beginCreateFieldMetadata(returnType, processReturnTypeUuid));
MetadataContext.cleanContext(processReturnTypeUuid);
// 填充方法的请求参数字段的详细信息
@ -325,7 +325,7 @@ public class ApiResourceScanner implements BeanPostProcessor {
MetadataContext.addParamTypeMetadata(parameterContextUuid, parameterMetadata.getParamTypeEnum());
MetadataContext.addParameterName(parameterContextUuid, parameterMetadata.getParameterName());
fieldMetadataLinkedHashSet.add(
ClassMetadataFactory.beginCreateFieldMetadata(parameterMetadata.getParameterizedType(), parameterContextUuid));
ClassMetaFactory.beginCreateFieldMetadata(parameterMetadata.getParameterizedType(), parameterContextUuid));
MetadataContext.cleanContext(parameterContextUuid);
}
resourceDefinition.setParamFieldDescriptions(fieldMetadataLinkedHashSet);