【resource】更新扫描资源,可以递归获取obj类型的字段详情,新增两个资源接口,用在生成api文档

pull/3/head
fengshuonan 2020-12-18 23:53:05 +08:00
parent 27680922e2
commit 1dc2507790
9 changed files with 226 additions and 27 deletions

View File

@ -12,7 +12,7 @@ import java.util.Set;
* @date 2020/12/8 18:25 * @date 2020/12/8 18:25
*/ */
@Data @Data
public class FieldDescription { public class FieldMetadata {
/** /**
* *
@ -42,4 +42,9 @@ public class FieldDescription {
*/ */
private Map<String, Set<String>> groupAnnotations; private Map<String, Set<String>> groupAnnotations;
/**
* object
*/
private Set<FieldMetadata> genericFieldMetadata;
} }

View File

@ -102,11 +102,11 @@ public class ResourceDefinition implements Serializable {
/** /**
* *
*/ */
private Set<FieldDescription> paramFieldDescriptions; private Set<FieldMetadata> paramFieldMetadata;
/** /**
* *
*/ */
private Set<FieldDescription> responseFieldDescriptions; private Set<FieldMetadata> responseFieldMetadata;
} }

View File

@ -2,7 +2,8 @@ package cn.stylefeng.roses.kernel.resource.api.util;
import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ClassUtil;
import cn.stylefeng.roses.kernel.resource.api.annotation.field.ChineseDescription; import cn.stylefeng.roses.kernel.resource.api.annotation.field.ChineseDescription;
import cn.stylefeng.roses.kernel.resource.api.pojo.resource.FieldDescription; import cn.stylefeng.roses.kernel.resource.api.pojo.resource.FieldMetadata;
import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -29,12 +30,12 @@ public class ClassReflectUtil {
* @author fengshuonan * @author fengshuonan
* @date 2020/12/8 18:27 * @date 2020/12/8 18:27
*/ */
public static Set<FieldDescription> getClassFieldDescription(Class<?> clazz) { public static Set<FieldMetadata> getClassFieldDescription(Class<?> clazz) {
HashSet<FieldDescription> fieldDescriptions = new HashSet<>(); HashSet<FieldMetadata> metadataHashSet = new HashSet<>();
if (clazz == null) { if (clazz == null) {
return fieldDescriptions; return metadataHashSet;
} }
// 获取类中的所有字段 // 获取类中的所有字段
@ -42,22 +43,27 @@ public class ClassReflectUtil {
for (Field declaredField : declaredFields) { for (Field declaredField : declaredFields) {
FieldDescription fieldDescription = new FieldDescription(); FieldMetadata fieldMetadata = new FieldMetadata();
// 获取字段的名称 // 获取字段的名称
String name = declaredField.getName(); String name = declaredField.getName();
fieldDescription.setFieldName(name); fieldMetadata.setFieldName(name);
// 获取字段的类型 // 获取字段的类型
Class<?> declaredFieldType = declaredField.getType(); Class<?> declaredFieldType = declaredField.getType();
fieldDescription.setFieldClassType(declaredFieldType.getSimpleName()); fieldMetadata.setFieldClassType(declaredFieldType.getSimpleName());
// 如果字段类型是Object类型则遍历Object类型里的字段
if (BaseRequest.class.isAssignableFrom(declaredFieldType)) {
fieldMetadata.setGenericFieldMetadata(getClassFieldDescription(declaredFieldType));
}
// 获取字段的所有注解 // 获取字段的所有注解
Annotation[] annotations = declaredField.getAnnotations(); Annotation[] annotations = declaredField.getAnnotations();
if (annotations != null && annotations.length > 0) { if (annotations != null && annotations.length > 0) {
// 设置字段的所有注解 // 设置字段的所有注解
fieldDescription.setAnnotations(annotationsToStrings(annotations)); fieldMetadata.setAnnotations(annotationsToStrings(annotations));
// 遍历字段上的所有注解找到带groups属性的按group分类组装注解 // 遍历字段上的所有注解找到带groups属性的按group分类组装注解
Map<String, Set<String>> groupAnnotations = new HashMap<>(); Map<String, Set<String>> groupAnnotations = new HashMap<>();
@ -70,19 +76,19 @@ public class ClassReflectUtil {
} }
} }
// 设置分组注解 // 设置分组注解
fieldDescription.setGroupAnnotations(groupAnnotations); fieldMetadata.setGroupAnnotations(groupAnnotations);
// 填充字段的中文名称 // 填充字段的中文名称
ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class); ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class);
if (chineseDescription != null) { if (chineseDescription != null) {
fieldDescription.setChineseName(chineseDescription.value()); fieldMetadata.setChineseName(chineseDescription.value());
} }
} }
fieldDescriptions.add(fieldDescription); metadataHashSet.add(fieldMetadata);
} }
return fieldDescriptions; return metadataHashSet;
} }
/** /**
@ -95,7 +101,7 @@ public class ClassReflectUtil {
try { try {
Class<? extends Annotation> annotationType = apiResource.annotationType(); Class<? extends Annotation> annotationType = apiResource.annotationType();
Method method = annotationType.getMethod(methodName); Method method = annotationType.getMethod(methodName);
return (T)method.invoke(apiResource); return (T) method.invoke(apiResource);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// 忽略异常 // 忽略异常
} }

View File

@ -257,15 +257,15 @@ public class ApiResourceScanner implements BeanPostProcessor {
// @ApiResource注解上标识了responseClass属性则用responseClass的值为准否则按真实方法的返回值class // @ApiResource注解上标识了responseClass属性则用responseClass的值为准否则按真实方法的返回值class
Class<?> responseClass = invokeAnnotationMethod(apiResource, "responseClass", Class.class); Class<?> responseClass = invokeAnnotationMethod(apiResource, "responseClass", Class.class);
if (!Void.class.equals(responseClass)) { if (!Void.class.equals(responseClass)) {
resourceDefinition.setResponseFieldDescriptions(ClassReflectUtil.getClassFieldDescription(responseClass)); resourceDefinition.setResponseFieldMetadata(ClassReflectUtil.getClassFieldDescription(responseClass));
} else { } else {
Class<?> methodReturnClass = MethodReflectUtil.getMethodReturnClass(method); Class<?> methodReturnClass = MethodReflectUtil.getMethodReturnClass(method);
resourceDefinition.setResponseFieldDescriptions(ClassReflectUtil.getClassFieldDescription(methodReturnClass)); resourceDefinition.setResponseFieldMetadata(ClassReflectUtil.getClassFieldDescription(methodReturnClass));
} }
// 填充方法的请求参数字段的详细信息 // 填充方法的请求参数字段的详细信息
Class<?> firstParamClass = MethodReflectUtil.getMethodFirstParamClass(method); Class<?> firstParamClass = MethodReflectUtil.getMethodFirstParamClass(method);
resourceDefinition.setParamFieldDescriptions(ClassReflectUtil.getClassFieldDescription(firstParamClass)); resourceDefinition.setParamFieldMetadata(ClassReflectUtil.getClassFieldDescription(firstParamClass));
return resourceDefinition; return resourceDefinition;
} }

View File

@ -1,8 +1,9 @@
package cn.stylefeng.roses.kernel.system.pojo.resource.request; package cn.stylefeng.roses.kernel.system.pojo.resource.request;
import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import javax.validation.constraints.NotBlank;
/** /**
* *
@ -11,7 +12,7 @@ import java.io.Serializable;
* @since 2019-09-10 * @since 2019-09-10
*/ */
@Data @Data
public class ResourceRequest implements Serializable { public class ResourceRequest extends BaseRequest {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -25,6 +26,12 @@ public class ResourceRequest implements Serializable {
*/ */
private String resourceName; private String resourceName;
/**
*
*/
@NotBlank(message = "资源编码为空", groups = detail.class)
private String resourceCode;
/** /**
* *
*/ */

View File

@ -56,13 +56,13 @@ public class ResourceFactory {
} }
// 转化接口参数的字段描述 // 转化接口参数的字段描述
if (ObjectUtil.isNotEmpty(resourceDefinition.getParamFieldDescriptions())) { if (ObjectUtil.isNotEmpty(resourceDefinition.getParamFieldMetadata())) {
resource.setParamFieldDescriptions(JSON.toJSONString(resourceDefinition.getParamFieldDescriptions(), SerializerFeature.WriteClassName)); resource.setParamFieldDescriptions(JSON.toJSONString(resourceDefinition.getParamFieldMetadata(), SerializerFeature.WriteClassName));
} }
// 转化接口返回结果的字段描述 // 转化接口返回结果的字段描述
if (ObjectUtil.isNotEmpty(resourceDefinition.getResponseFieldDescriptions())) { if (ObjectUtil.isNotEmpty(resourceDefinition.getResponseFieldMetadata())) {
resource.setResponseFieldDescriptions(JSON.toJSONString(resourceDefinition.getResponseFieldDescriptions(), SerializerFeature.WriteClassName)); resource.setResponseFieldDescriptions(JSON.toJSONString(resourceDefinition.getResponseFieldMetadata(), SerializerFeature.WriteClassName));
} }
return resource; return resource;
@ -94,12 +94,12 @@ public class ResourceFactory {
// 转化接口参数的字段描述 // 转化接口参数的字段描述
if (ObjectUtil.isNotEmpty(sysResource.getParamFieldDescriptions())) { if (ObjectUtil.isNotEmpty(sysResource.getParamFieldDescriptions())) {
resourceDefinition.setParamFieldDescriptions(JSON.parseObject(sysResource.getParamFieldDescriptions(), Set.class, Feature.SupportAutoType)); resourceDefinition.setParamFieldMetadata(JSON.parseObject(sysResource.getParamFieldDescriptions(), Set.class, Feature.SupportAutoType));
} }
// 转化接口返回结果的字段描述 // 转化接口返回结果的字段描述
if (ObjectUtil.isNotEmpty(sysResource.getResponseFieldDescriptions())) { if (ObjectUtil.isNotEmpty(sysResource.getResponseFieldDescriptions())) {
resourceDefinition.setResponseFieldDescriptions(JSON.parseObject(sysResource.getResponseFieldDescriptions(), Set.class, Feature.SupportAutoType)); resourceDefinition.setResponseFieldMetadata(JSON.parseObject(sysResource.getResponseFieldDescriptions(), Set.class, Feature.SupportAutoType));
} }
return resourceDefinition; return resourceDefinition;

View File

@ -0,0 +1,44 @@
package cn.stylefeng.roses.kernel.resource.modular.pojo;
import lombok.Data;
import java.util.List;
/**
*
*
* @author fengshuonan
* @date 2020/3/26 14:29
*/
@Data
public class ResourceTreeNode {
/**
* id
*/
private String code;
/**
* id
*/
private String parentCode;
/**
*
*/
private String nodeName;
/**
*
* <p>
* true-
* false-
*/
private Boolean resourceFlag;
/**
*
*/
private List children;
}

View File

@ -1,6 +1,8 @@
package cn.stylefeng.roses.kernel.resource.modular.service; package cn.stylefeng.roses.kernel.resource.modular.service;
import cn.stylefeng.roses.kernel.resource.api.pojo.resource.ResourceDefinition;
import cn.stylefeng.roses.kernel.resource.modular.entity.SysResource; import cn.stylefeng.roses.kernel.resource.modular.entity.SysResource;
import cn.stylefeng.roses.kernel.resource.modular.pojo.ResourceTreeNode;
import cn.stylefeng.roses.kernel.system.pojo.resource.request.ResourceRequest; import cn.stylefeng.roses.kernel.system.pojo.resource.request.ResourceRequest;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
@ -46,4 +48,23 @@ public interface SysResourceService extends IService<SysResource> {
*/ */
void deleteResourceByProjectCode(String projectCode); void deleteResourceByProjectCode(String projectCode);
/**
* api
*
* @return
* @author fengshuonan
* @date 2020/12/18 15:06
*/
List<ResourceTreeNode> getResourceTree();
/**
*
*
* @param resourceRequest
* @return
* @author fengshuonan
* @date 2020/12/18 16:04
*/
ResourceDefinition getResourceDetail(ResourceRequest resourceRequest);
} }

View File

@ -10,6 +10,7 @@ import cn.stylefeng.roses.kernel.resource.modular.cache.ResourceCache;
import cn.stylefeng.roses.kernel.resource.modular.entity.SysResource; import cn.stylefeng.roses.kernel.resource.modular.entity.SysResource;
import cn.stylefeng.roses.kernel.resource.modular.factory.ResourceFactory; import cn.stylefeng.roses.kernel.resource.modular.factory.ResourceFactory;
import cn.stylefeng.roses.kernel.resource.modular.mapper.SysResourceMapper; import cn.stylefeng.roses.kernel.resource.modular.mapper.SysResourceMapper;
import cn.stylefeng.roses.kernel.resource.modular.pojo.ResourceTreeNode;
import cn.stylefeng.roses.kernel.resource.modular.service.SysResourceService; import cn.stylefeng.roses.kernel.resource.modular.service.SysResourceService;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum; import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.system.ResourceServiceApi; import cn.stylefeng.roses.kernel.system.ResourceServiceApi;
@ -25,10 +26,13 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.stylefeng.roses.kernel.system.constants.SystemConstants.DEFAULT_PARENT_ID;
/** /**
* *
* *
@ -80,6 +84,33 @@ public class SysResourceServiceImpl extends ServiceImpl<SysResourceMapper, SysRe
this.remove(wrapper); this.remove(wrapper);
} }
@Override
public List<ResourceTreeNode> getResourceTree() {
// 1. 获取所有的资源
LambdaQueryWrapper<SysResource> sysResourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
sysResourceLambdaQueryWrapper.select(SysResource::getAppCode, SysResource::getModularCode, SysResource::getModularName, SysResource::getCode, SysResource::getUrl, SysResource::getName);
List<SysResource> allResource = this.list(sysResourceLambdaQueryWrapper);
// 2. 按应用和模块编码设置map
Map<String, Map<String, List<ResourceTreeNode>>> appModularResources = divideResources(allResource);
// 3. 根据map组装资源树
return createResourceTree(appModularResources);
}
@Override
public ResourceDefinition getResourceDetail(ResourceRequest resourceRequest) {
LambdaQueryWrapper<SysResource> sysResourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
sysResourceLambdaQueryWrapper.eq(SysResource::getCode, resourceRequest.getResourceCode());
SysResource sysResource = this.getOne(sysResourceLambdaQueryWrapper);
if (sysResource != null) {
return ResourceFactory.createResourceDefinition(sysResource);
} else {
return null;
}
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void reportResources(@RequestBody ReportResourceParam reportResourceReq) { public void reportResources(@RequestBody ReportResourceParam reportResourceReq) {
@ -216,4 +247,89 @@ public class SysResourceServiceImpl extends ServiceImpl<SysResourceMapper, SysRe
return queryWrapper; return queryWrapper;
} }
/**
*
*
* @return keykey
* @author fengshuonan
* @date 2020/12/18 15:34
*/
private Map<String, Map<String, List<ResourceTreeNode>>> divideResources(List<SysResource> sysResources) {
HashMap<String, Map<String, List<ResourceTreeNode>>> appModularResources = new HashMap<>();
for (SysResource sysResource : sysResources) {
// 查询应用下有无资源
String appCode = sysResource.getAppCode();
Map<String, List<ResourceTreeNode>> modularResource = appModularResources.get(appCode);
// 该应用下没资源就创建一个map
if (modularResource == null) {
modularResource = new HashMap<>();
}
// 查询当前资源的模块有没有在appModularResources存在
List<ResourceTreeNode> resourceTreeNodes = modularResource.get(sysResource.getModularCode());
if (resourceTreeNodes == null) {
resourceTreeNodes = new ArrayList<>();
}
// 将当前资源放入资源集合
ResourceTreeNode resourceTreeNode = new ResourceTreeNode();
resourceTreeNode.setResourceFlag(true);
resourceTreeNode.setNodeName(sysResource.getUrl() + "(" + sysResource.getName() + ")");
resourceTreeNode.setCode(sysResource.getCode());
resourceTreeNode.setParentCode(sysResource.getModularCode());
resourceTreeNodes.add(resourceTreeNode);
modularResource.put(sysResource.getModularCode(), resourceTreeNodes);
appModularResources.put(appCode, modularResource);
}
return appModularResources;
}
/**
*
*
* @author fengshuonan
* @date 2020/12/18 15:45
*/
private List<ResourceTreeNode> createResourceTree(Map<String, Map<String, List<ResourceTreeNode>>> appModularResources) {
List<ResourceTreeNode> finalTree = new ArrayList<>();
// 按应用遍历应用模块资源集合
for (String appName : appModularResources.keySet()) {
// 创建当前应用节点
ResourceTreeNode appNode = new ResourceTreeNode();
appNode.setCode(appName);
appNode.setNodeName(appName);
appNode.setResourceFlag(false);
appNode.setParentCode(DEFAULT_PARENT_ID.toString());
// 遍历当前应用下的模块资源
Map<String, List<ResourceTreeNode>> modularResources = appModularResources.get(appName);
// 创建模块节点
ArrayList<ResourceTreeNode> modularNodes = new ArrayList<>();
for (String modularName : modularResources.keySet()) {
ResourceTreeNode modularNode = new ResourceTreeNode();
modularNode.setCode(modularName);
modularNode.setNodeName(modularName);
modularNode.setResourceFlag(false);
modularNode.setParentCode(appName);
modularNode.setChildren(modularResources.get(modularName));
modularNodes.add(modularNode);
}
// 当前应用下添加模块的资源
appNode.setChildren(modularNodes);
// 添加到最终结果
finalTree.add(appNode);
}
return finalTree;
}
} }