package org.ssssssss.magicapi.core.service.impl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.ssssssss.magicapi.core.config.Constants;
import org.ssssssss.magicapi.core.config.JsonCodeConstants;
import org.ssssssss.magicapi.core.resource.Resource;
import org.ssssssss.magicapi.core.resource.ZipResource;
import org.ssssssss.magicapi.core.event.EventAction;
import org.ssssssss.magicapi.core.event.FileEvent;
import org.ssssssss.magicapi.core.event.GroupEvent;
import org.ssssssss.magicapi.core.event.MagicEvent;
import org.ssssssss.magicapi.core.exception.InvalidArgumentException;
import org.ssssssss.magicapi.core.model.*;
import org.ssssssss.magicapi.core.service.AbstractPathMagicResourceStorage;
import org.ssssssss.magicapi.core.service.MagicResourceService;
import org.ssssssss.magicapi.core.service.MagicResourceStorage;
import org.ssssssss.magicapi.utils.IoUtils;
import org.ssssssss.magicapi.utils.JsonUtils;
import org.ssssssss.magicapi.utils.WebUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class DefaultMagicResourceService implements MagicResourceService, JsonCodeConstants, ApplicationListener<ApplicationStartedEvent> {
private final Resource root;
private final Map<String, Resource> groupMappings = new HashMap<>(16);
private final Map<String, Group> groupCache = new HashMap<>(16);
private final Map<String, Resource> fileMappings = new HashMap<>(32);
private final Map<String, MagicEntity> fileCache = new HashMap<>(32);
private final Map<String, Map<String, String>> pathCache = new HashMap<>(16);
private final Map<String, MagicResourceStorage<? extends MagicEntity>> storages;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final ApplicationEventPublisher publisher;
private final Logger logger = LoggerFactory.getLogger(DefaultMagicResourceService.class);
public DefaultMagicResourceService(Resource resource, List<MagicResourceStorage<? extends MagicEntity>> storages, ApplicationEventPublisher publisher) {
this.root = resource;
this.storages = storages.stream()
.peek(it -> it.setMagicResourceService(this))
.collect(Collectors.toMap(MagicResourceStorage::folder, it -> it));
this.publisher = publisher;
}
public boolean processNotify(MagicNotify notify) {
if (Constants.EVENT_TYPE_FILE.equals(notify.getType())) {
return processFileNotify(notify.getId(), notify.getAction());
}
if (notify.getAction() == EventAction.CLEAR) {
this.read(false);
return true;
}
return processGroupNotify(notify.getId(), notify.getAction());
}
private boolean processGroupNotify(String id, EventAction action) {
Group group = groupCache.get(id);
if (group == null) {
// create
this.readAll();
group = groupCache.get(id);
}
TreeNode<Group> treeNode = tree(group.getType()).findTreeNode(it -> it.getId().equals(id));
if (treeNode != null) {
GroupEvent event = new GroupEvent(group.getType(), action, group);
event.setSource(Constants.EVENT_SOURCE_NOTIFY);
if (event.getAction() == EventAction.DELETE) {
event.setEntities(deleteGroup(id));
} else if (action != EventAction.CREATE) {
Resource folder = groupMappings.get(id);
folder.readAll();
if (folder.exists()) {
// 刷新分组缓存
refreshGroup(folder, storages.get(group.getType()));
} else {
this.readAll();
treeNode = tree(group.getType()).findTreeNode(it -> it.getId().equals(id));
}
event.setGroup(groupCache.get(id));
event.setEntities(treeNode
.flat()
.stream()
.flatMap(g -> listFiles(g.getId()).stream())
.collect(Collectors.toList()));
}
publisher.publishEvent(event);
return true;
}
return false;
}
private boolean processFileNotify(String id, EventAction action) {
MagicEntity entity = fileCache.get(id);
if (entity == null) { // create
this.readAll();
entity = fileCache.get(id);
}
if (entity != null) {
Group group = groupCache.get(entity.getGroupId());
if (group != null) {
MagicResourceStorage<? extends MagicEntity> storage = storages.get(group.getType());
Map<String, String> pathCacheMap = storage.requirePath() ? pathCache.get(storage.folder()) : null;
if (action == EventAction.DELETE) {
fileMappings.remove(id);
entity = fileCache.remove(id);
if (pathCacheMap != null) {
pathCacheMap.remove(id);
}
} else {
Resource resource = fileMappings.get(id);
resource.readAll();
if (resource.exists()) {
entity = storage.read(resource.read());
putFile(storage, entity, resource);
} else {
this.readAll();
entity = fileCache.get(id);
}
}
publisher.publishEvent(new FileEvent(group.getType(), action, entity, Constants.EVENT_SOURCE_NOTIFY));
}
}
return false;
}
private void init() {
groupMappings.clear();
groupCache.clear();
fileMappings.clear();
fileCache.clear();
pathCache.clear();
storages.forEach((key, registry) -> {
if (registry.requirePath()) {
pathCache.put(registry.folder(), new HashMap<>(32));
}
Resource folder = root.getDirectory(key);
if (registry.allowRoot()) {
String rootId = key + ":0";
Group group = new Group();
group.setId(rootId);
group.setType(key);
group.setParentId("0");
putGroup(group, folder);
}
if (!folder.exists()) {
folder.mkdir();
}
});
}
private void read(boolean triggerEvent) {
writeLock(() -> {
if (triggerEvent) {
publisher.publishEvent(new MagicEvent("clear", EventAction.CLEAR));
}
this.readAll();
fileCache.values().forEach(entity -> {
Group group = groupCache.get(entity.getGroupId());
publisher.publishEvent(new FileEvent(group.getType(), EventAction.LOAD, entity));
});
return null;
});
}
private void readAll() {
writeLock(() -> {
this.init();
this.root.readAll();
storages.forEach((key, registry) -> refreshGroup(root.getDirectory(key), registry));
return null;
});
}
@Override
public void refresh() {
this.read(true);
}
@Override
public Resource getResource() {
return root;
}
private void refreshGroup(Resource folder, MagicResourceStorage<? extends MagicEntity> storage) {
if (storage.allowRoot()) {
folder.files(storage.suffix()).forEach(file -> putFile(storage, storage.readResource(file), file));
} else {
folder.dirs().forEach(dir -> {
Resource meta = dir.getResource(Constants.GROUP_METABASE);
if (meta.exists()) {
putGroup(JsonUtils.readValue(meta.read(), Group.class), dir);
dir.files(storage.suffix()).forEach(file -> putFile(storage, storage.readResource(file), file));
}
});
}
}
@Override
public boolean saveGroup(Group group) {
isTrue(!root.readonly(), IS_READ_ONLY);
// 类型校验
isTrue(storages.containsKey(group.getType()), NOT_SUPPORTED_GROUP_TYPE);
// 名字校验
notNull(group.getName(), NAME_REQUIRED);
notNull(IoUtils.validateFileName(group.getName()), NAME_INVALID);
// 需要填写parentId
notNull(group.getParentId(), GROUP_ID_REQUIRED);
MagicResourceStorage<? extends MagicEntity> storage = storages.get(group.getType());
return writeLock(() -> {
Resource resource;
// 判断是否要保存到根节点下
if (Constants.ROOT_ID.equals(group.getParentId())) {
resource = root.getDirectory(group.getType());
} else {
// 找到上级分组
resource = getGroupResource(group.getParentId());
// 上级分组�
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
本源码项目是基于Java的magic-api接口快速开发框架设计,包含320个文件,主要使用Java、JavaScript、Vue、HTML和CSS编程语言。该项目是一个接口快速开发框架,旨在帮助开发者更高效地完成HTTP API接口的开发。通过magic-api提供的UI界面,开发者可以方便地编写接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象。系统界面友好,易于操作,适合用于各类接口开发场景。
资源推荐
资源详情
资源评论
收起资源包目录
基于Java的magic-api接口快速开发框架设计源码 (318个子文件)
style.07c46cc4.css 122KB
spring.factories 134B
spring.factories 131B
spring.factories 130B
spring.factories 124B
spring.factories 119B
spring.factories 119B
spring.factories 115B
spring.factories 115B
spring.factories 111B
.gitattributes 86B
.gitignore 69B
index.html 3KB
org.springframework.boot.autoconfigure.AutoConfiguration.imports 70B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 67B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 67B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 60B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 59B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 55B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 55B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 51B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 51B
org.springframework.boot.autoconfigure.AutoConfiguration.imports 47B
DefaultMagicResourceService.java 30KB
SQLModule.java 26KB
RequestHandler.java 21KB
NamedTable.java 21KB
MagicAPIAutoConfiguration.java 20KB
Where.java 17KB
MagicWorkbenchController.java 12KB
SwaggerEntity.java 12KB
SwaggerEntity.java 12KB
SwaggerProvider.java 10KB
SwaggerProvider.java 10KB
DefaultMagicAPIService.java 8KB
MagicModuleConfiguration.java 8KB
MagicAPIProperties.java 8KB
ClassScanner.java 8KB
WebSocketSessionManager.java 7KB
MagicResourceController.java 7KB
Formatter.java 7KB
MagicDynamicDataSource.java 6KB
MagicSpringDocConfiguration.java 6KB
GitRepo.java 6KB
HttpModule.java 6KB
DatabaseResource.java 6KB
MagicConfiguration.java 6KB
ApiInfo.java 6KB
RequestMagicDynamicRegistry.java 5KB
MagicSwaggerConfiguration.java 5KB
MagicDatabaseBackupService.java 5KB
BoundSql.java 5KB
DataSourceMagicDynamicRegistry.java 5KB
MagicWebSocketDispatcher.java 5KB
AbstractMagicDynamicRegistry.java 5KB
MagicWorkbenchHandler.java 4KB
RedisModule.java 4KB
ResponseModule.java 4KB
MybatisParser.java 4KB
KeyValueResource.java 4KB
Resource.java 4KB
JsonCodeConstants.java 4KB
IoUtils.java 4KB
MongoCollectionExtension.java 4KB
FileResource.java 4KB
JarResource.java 4KB
MagicController.java 4KB
MagicJakartaHttpServletRequest.java 4KB
MagicJavaEEHttpServletRequest.java 4KB
ResultProvider.java 4KB
MagicBackupController.java 4KB
RedisResource.java 4KB
TaskMagicDynamicRegistry.java 4KB
ZipResource.java 3KB
Mapping.java 3KB
RequestInterceptor.java 3KB
GitResource.java 3KB
MongoModule.java 3KB
MagicJakartaResponseExtension.java 3KB
MagicJavaEEResponseExtension.java 3KB
RequestModule.java 3KB
BaseDefinition.java 3KB
LRUCache.java 3KB
MagicJsonAutoConfiguration.java 3KB
RequestEntity.java 3KB
Group.java 3KB
Constants.java 3KB
MagicDynamicRegistryConfiguration.java 3KB
DataType.java 3KB
MagicJakartaServletConfiguration.java 3KB
MagicJavaEEServletConfiguration.java 3KB
JsonUtils.java 3KB
ElasticSearchIndex.java 3KB
MagicClusterConfiguration.java 3KB
FunctionMagicDynamicRegistry.java 3KB
AuthorizationInterceptor.java 3KB
FunctionInfo.java 3KB
SpringDocConfig.java 3KB
MagicResourceService.java 3KB
MagicEntity.java 2KB
共 318 条
- 1
- 2
- 3
- 4
资源评论
沐知全栈开发
- 粉丝: 5821
- 资源: 5227
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Ollama安装文件,从官网下载
- 数据库编程中Cursor(游标)的概念、功能与应用场景解析
- 通过 OpenCV 加载视频文件 1.mp4,并使用 YOLOv8 模型进行姿态检测 它逐帧处理视频,检测人体关键点并绘制关键点及其连接 具体来说,代码首先加载 YOLOv8 模型并定义了关键点之间的
- 1ef69c3e3bfa6ebc829f03a871190d69.part01
- 9.6.0.3_1d9317597fbe653ff1d29cfaacfca6b8.apk
- lv_0_20250204142911.mp4
- NASA锂电池数据集(补).zip
- 面向对象课程设计基于Java+MySQL+JDBC+JavaSwing的图书信息管理系统源代码+数据库+课程设计报告
- DHCP服务租约和续约过程流程图
- 1ef69c3e3bfa6ebc829f03a871190d69.part02
- 1ef69c3e3bfa6ebc829f03a871190d69.part03
- 1ef69c3e3bfa6ebc829f03a871190d69.part04
- 基于Servlet+Jsp+MySQL的艺术作品展览管理系统源代码+数据库
- 1ef69c3e3bfa6ebc829f03a871190d69.part05
- 1ef69c3e3bfa6ebc829f03a871190d69.part06
- 财务收支数据年终报表-可视化图表.xlsx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功