新增扫描list集合的方法(待完善)

pull/22/head
rays 2021-06-23 17:52:57 +08:00
parent af10986b45
commit d40af1f6d7
7 changed files with 166 additions and 74 deletions

View File

@ -59,6 +59,12 @@ public class FieldMetadata {
@ChineseDescription("字段类型")
private String fieldClassType;
/**
* java.long.String
*/
@ChineseDescription("字段类型路径")
private String fieldClassPath;
/**
* createUser
*/

View File

@ -26,15 +26,14 @@ package cn.stylefeng.roses.kernel.scanner.api.util;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.TypeUtil;
import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest;
import cn.stylefeng.roses.kernel.scanner.api.annotation.field.ChineseDescription;
import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.*;
import java.util.*;
/**
@ -45,6 +44,8 @@ import java.util.*;
*/
public class ClassReflectUtil {
private static Map<String, String> runingMap = new HashMap<>(2);
/**
*
*
@ -54,83 +55,123 @@ public class ClassReflectUtil {
* @date 2020/12/8 18:27
*/
public static Set<FieldMetadata> getClassFieldDescription(Class<?> clazz) {
HashSet<FieldMetadata> fieldDescriptions = new HashSet<>();
if (clazz == null) {
return fieldDescriptions;
}
// 查询本类是否正在进行解析(防止死循环)
String runing = runingMap.get(clazz.getName());
// 返回null则标识这个类正在运行则不对该类再进行解析
if (ObjectUtil.isNotEmpty(runing)) {
return null;
}
// 获取该类和该类所有父类的属性
while (clazz != null){
while (clazz != null) {
runingMap.put(clazz.getName(), clazz.getName());
// 获取类中的所有字段
Field[] declaredFields = ClassUtil.getDeclaredFields(clazz);
for (Field declaredField : declaredFields) {
FieldMetadata fieldDescription = new FieldMetadata();
// 生成uuid给前端用
fieldDescription.setMetadataId(IdUtil.fastSimpleUUID());
// 获取字段的名称
String name = declaredField.getName();
fieldDescription.setFieldName(name);
// 获取字段的类型
Class<?> declaredFieldType = declaredField.getType();
fieldDescription.setFieldClassType(declaredFieldType.getSimpleName());
// 如果字段类型是Object类型则遍历Object类型里的字段
if (BaseRequest.class.isAssignableFrom(declaredFieldType)) {
fieldDescription.setGenericFieldMetadata(getClassFieldDescription(declaredFieldType));
}
// 如果是泛型类型遍历泛泛型的class类型里的字段
if (Collection.class.isAssignableFrom(declaredFieldType)) {
Class<?> genericClass = TypeUtil.getClass(TypeUtil.getTypeArgument(TypeUtil.getType(declaredField)));
if (BaseRequest.class.isAssignableFrom(genericClass)) {
fieldDescription.setGenericFieldMetadata(getClassFieldDescription(genericClass));
}
}
// 获取字段的所有注解
Annotation[] annotations = declaredField.getAnnotations();
if (annotations != null && annotations.length > 0) {
// 设置字段的所有注解
fieldDescription.setAnnotations(annotationsToStrings(annotations));
// 遍历字段上的所有注解找到带groups属性的按group分类组装注解
Map<String, Set<String>> groupAnnotations = new HashMap<>();
for (Annotation annotation : annotations) {
Class<?>[] validateGroupsClasses = invokeAnnotationMethodIgnoreError(annotation, "groups", Class[].class);
if (validateGroupsClasses != null) {
for (Class<?> validateGroupsClass : validateGroupsClasses) {
addGroupValidateAnnotation(annotation, validateGroupsClass, groupAnnotations);
}
}
}
// 设置分组注解
fieldDescription.setGroupValidationMessage(groupAnnotations);
// 填充字段的中文名称
ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class);
if (chineseDescription != null) {
fieldDescription.setChineseName(chineseDescription.value());
}
}
// 获取字段元数据
FieldMetadata fieldDescription = getFieldMetadata(declaredField);
fieldDescriptions.add(fieldDescription);
}
runingMap.remove(clazz.getName());
// 获取本类的父类
clazz = clazz.getSuperclass();
}
return fieldDescriptions;
}
/**
*
*
* @param declaredField
* @return {@link cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata}
* @author majianguo
* @date 2021/6/23 10:03
**/
private static FieldMetadata getFieldMetadata(Field declaredField) {
FieldMetadata fieldDescription = new FieldMetadata();
// 生成uuid给前端用
fieldDescription.setMetadataId(IdUtil.fastSimpleUUID());
// 获取字段的名称
String name = declaredField.getName();
fieldDescription.setFieldName(name);
// 获取字段的类型
Class<?> declaredFieldType = declaredField.getType();
fieldDescription.setFieldClassType(declaredFieldType.getSimpleName());
fieldDescription.setFieldClassPath(declaredFieldType.getName());
// 如果字段类型是Object类型则遍历Object类型里的字段
if (BaseRequest.class.isAssignableFrom(declaredFieldType)) {
fieldDescription.setGenericFieldMetadata(getClassFieldDescription(declaredFieldType));
} else if (List.class.isAssignableFrom(declaredFieldType)) {
// 如果是集合类型,则处理集合里面的字段
Type genericType = declaredField.getGenericType();
ParameterizedType pt = (ParameterizedType)genericType;
// 得到泛型里的class类型对象
Class<?> actualTypeArgument = (Class<?>)pt.getActualTypeArguments()[0];
// 基本类型处理
if (actualTypeArgument.isPrimitive() || "java.lang".equals(actualTypeArgument.getPackage().getName()) || "java.util".equals(actualTypeArgument.getPackage().getName())) {
FieldMetadata item = new FieldMetadata();
item.setMetadataId(IdUtil.fastSimpleUUID());
item.setFieldName(actualTypeArgument.getName());
item.setFieldClassType(actualTypeArgument.getTypeName());
// 填充字段的中文名称
ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class);
if (chineseDescription != null) {
item.setChineseName(chineseDescription.value());
}
fieldDescription.setGenericFieldMetadata(Collections.singleton(item));
} else {
fieldDescription.setGenericFieldMetadata(getClassFieldDescription(actualTypeArgument));
}
} else if (Collection.class.isAssignableFrom(declaredFieldType)) {
// 如果是泛型类型遍历泛泛型的class类型里的字段
Class<?> genericClass = TypeUtil.getClass(TypeUtil.getTypeArgument(TypeUtil.getType(declaredField)));
if (BaseRequest.class.isAssignableFrom(genericClass)) {
fieldDescription.setGenericFieldMetadata(getClassFieldDescription(genericClass));
}
}
// 获取字段的所有注解
Annotation[] annotations = declaredField.getAnnotations();
if (annotations != null && annotations.length > 0) {
// 设置字段的所有注解
fieldDescription.setAnnotations(annotationsToStrings(annotations));
// 遍历字段上的所有注解找到带groups属性的按group分类组装注解
Map<String, Set<String>> groupAnnotations = new HashMap<>();
for (Annotation annotation : annotations) {
Class<?>[] validateGroupsClasses = invokeAnnotationMethodIgnoreError(annotation, "groups", Class[].class);
if (validateGroupsClasses != null) {
for (Class<?> validateGroupsClass : validateGroupsClasses) {
addGroupValidateAnnotation(annotation, validateGroupsClass, groupAnnotations);
}
}
}
// 设置分组注解
fieldDescription.setGroupValidationMessage(groupAnnotations);
// 填充字段的中文名称
ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class);
if (chineseDescription != null) {
fieldDescription.setChineseName(chineseDescription.value());
}
}
return fieldDescription;
}
/**
*
*

View File

@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Set;
/**
*
@ -64,6 +65,11 @@ public class ApiResourceFieldRequest extends BaseRequest {
*/
private String fieldValidationMsg;
/**
* (ObjectList)
*/
private Set<ApiResourceFieldRequest> children;
/**
*
*/

View File

@ -2,6 +2,7 @@ package cn.stylefeng.roses.kernel.system.modular.resource.entity;
import cn.stylefeng.roses.kernel.db.api.pojo.entity.BaseEntity;
import cn.stylefeng.roses.kernel.scanner.api.annotation.field.ChineseDescription;
import cn.stylefeng.roses.kernel.system.api.pojo.resource.ApiResourceFieldRequest;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@ -115,6 +116,6 @@ public class ApiResource extends BaseEntity {
*/
@TableField(exist = false)
@ChineseDescription("该资源所有字段")
private List<ApiResourceField> apiResourceFieldList;
private List<ApiResourceFieldRequest> apiResourceFieldList;
}

View File

@ -58,7 +58,7 @@ public class ApiResourceField extends BaseEntity {
private String fieldCode;
/**
* stringfile
* stringfileListObject
*/
@TableField("field_type")
@ChineseDescription("字段类型")
@ -78,6 +78,13 @@ public class ApiResourceField extends BaseEntity {
@ChineseDescription("字段其他校验信息,后端校验注解内容")
private String fieldValidationMsg;
/**
* (ObjectList)
*/
@TableField("field_sub_info")
@ChineseDescription("字段子字段信息(Object和List会用到)")
private String fieldSubInfo;
/**
*
*/

View File

@ -2,6 +2,7 @@ package cn.stylefeng.roses.kernel.system.modular.resource.service;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.system.api.pojo.resource.ApiGroupRequest;
import cn.stylefeng.roses.kernel.system.api.pojo.resource.ApiResourceFieldRequest;
import cn.stylefeng.roses.kernel.system.api.pojo.resource.ApiResourceRequest;
import cn.stylefeng.roses.kernel.system.modular.resource.entity.ApiResource;
import cn.stylefeng.roses.kernel.system.modular.resource.entity.ApiResourceField;
@ -87,7 +88,7 @@ public interface ApiResourceService extends IService<ApiResource> {
* @author majianguo
* @date 2021/5/24 6:45
**/
List<ApiResourceField> allField(ApiResourceRequest apiResourceRequest);
List<ApiResourceFieldRequest> allField(ApiResourceRequest apiResourceRequest);
/**
*

View File

@ -29,6 +29,7 @@ import cn.stylefeng.roses.kernel.system.modular.resource.service.SysResourceServ
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -38,10 +39,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMethod;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -221,7 +219,16 @@ public class ApiResourceServiceImpl extends ServiceImpl<ApiResourceMapper, ApiRe
List<ApiResourceField> apiResourceFields = this.apiResourceFieldService.list(apiResourceFieldLambdaQueryWrapper);
// 过滤创建时间和创建人
apiResourceFields.removeIf(resourceField -> "createTime".equalsIgnoreCase(resourceField.getFieldCode()) || "createUser".equalsIgnoreCase(resourceField.getFieldCode()) || "updateTime".equalsIgnoreCase(resourceField.getFieldCode()) || "updateUser".equalsIgnoreCase(resourceField.getFieldCode()));
apiResource.setApiResourceFieldList(apiResourceFields);
List<ApiResourceFieldRequest> apiResourceFieldList = new ArrayList<>();
for (ApiResourceField apiResourceField : apiResourceFields) {
// 转换为前端对象
ApiResourceFieldRequest apiResourceFieldRequest = BeanUtil.toBean(apiResourceField, ApiResourceFieldRequest.class);
apiResourceFieldRequest.setChildren(JSON.parseObject(apiResourceField.getFieldSubInfo(), Set.class, Feature.SupportAutoType));
apiResourceFieldList.add(apiResourceFieldRequest);
}
apiResource.setApiResourceFieldList(apiResourceFieldList);
return apiResource;
}
@ -282,7 +289,7 @@ public class ApiResourceServiceImpl extends ServiceImpl<ApiResourceMapper, ApiRe
}
@Override
public List<ApiResourceField> allField(ApiResourceRequest apiResourceRequest) {
public List<ApiResourceFieldRequest> allField(ApiResourceRequest apiResourceRequest) {
LambdaQueryWrapper<SysResource> sysResourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
sysResourceLambdaQueryWrapper.eq(SysResource::getResourceCode, apiResourceRequest.getResourceCode());
SysResource sysResources = sysResourceService.getOne(sysResourceLambdaQueryWrapper);
@ -291,20 +298,28 @@ public class ApiResourceServiceImpl extends ServiceImpl<ApiResourceMapper, ApiRe
ResourceDefinition fillResourceDetail = ResourceFactory.fillResourceDetail(ResourceFactory.createResourceDefinition(sysResources));
// 把所有字段加进去
List<ApiResourceField> apiResourceFieldList = new ArrayList<>();
List<ApiResourceFieldRequest> apiResourceFieldList = new ArrayList<>();
if (ObjectUtil.isNotEmpty(fillResourceDetail.getParamFieldDescriptions())) {
// 处理所有请求字段
for (FieldMetadata fieldMetadata : fillResourceDetail.getParamFieldDescriptions()) {
ApiResourceField conversion = this.conversion(sysResources, null, fieldMetadata);
conversion.setFieldLocation("request");
apiResourceFieldList.add(conversion);
// 转换为前端对象
ApiResourceFieldRequest apiResourceFieldRequest = BeanUtil.toBean(conversion, ApiResourceFieldRequest.class);
apiResourceFieldRequest.setChildren(JSON.parseObject(conversion.getFieldSubInfo(), Set.class, Feature.SupportAutoType));
apiResourceFieldList.add(apiResourceFieldRequest);
}
// 处理所有响应字段
for (FieldMetadata fieldDescription : fillResourceDetail.getResponseFieldDescriptions()) {
ApiResourceField conversion = this.conversion(sysResources, null, fieldDescription);
conversion.setFieldLocation("response");
apiResourceFieldList.add(conversion);
// 转换为前端对象
ApiResourceFieldRequest apiResourceFieldRequest = BeanUtil.toBean(conversion, ApiResourceFieldRequest.class);
apiResourceFieldRequest.setChildren(JSON.parseObject(conversion.getFieldSubInfo(), Set.class, Feature.SupportAutoType));
apiResourceFieldList.add(apiResourceFieldRequest);
}
}
return apiResourceFieldList;
@ -400,7 +415,11 @@ public class ApiResourceServiceImpl extends ServiceImpl<ApiResourceMapper, ApiRe
item.setApiResourceId(apiResourceId);
item.setFieldCode(fieldMetadata.getFieldName());
item.setFieldName(fieldMetadata.getChineseName());
if ("file".equalsIgnoreCase(fieldMetadata.getFieldClassType())) {
if ("cn.stylefeng.".contains(fieldMetadata.getFieldClassPath())) {
item.setFieldType("object");
} else if ("java.util".contains(fieldMetadata.getFieldClassPath())) {
item.setFieldType("list");
} else if ("java.io".contains(fieldMetadata.getFieldClassPath())) {
item.setFieldType("file");
} else {
item.setFieldType("string");
@ -412,6 +431,17 @@ public class ApiResourceServiceImpl extends ServiceImpl<ApiResourceMapper, ApiRe
// 字段校验消息
item.setFieldValidationMsg(fieldMetadata.getValidationMessages());
// 如果还有子字段,则处理字段
Set<FieldMetadata> genericFieldMetadata = fieldMetadata.getGenericFieldMetadata();
if (ObjectUtil.isNotEmpty(genericFieldMetadata)) {
Set<ApiResourceField> apiResourceFieldSet = new HashSet<>();
for (FieldMetadata genericFieldMetadatum : genericFieldMetadata) {
ApiResourceField conversion = this.conversion(sysResource, apiResourceId, genericFieldMetadatum);
apiResourceFieldSet.add(conversion);
}
item.setFieldSubInfo(JSON.toJSONString(apiResourceFieldSet, SerializerFeature.WriteClassName));
}
return item;
}