接口选项,分组选项,分组路径,屏蔽备份
This commit is contained in:
parent
663a7d9588
commit
a4c3dcd3c7
@ -71,7 +71,6 @@ import org.ssssssss.script.reflection.JavaReflection;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.sql.DataSource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
@ -398,13 +397,6 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketCon
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MagicBackupService.class)
|
||||
@ConditionalOnProperty(prefix = "magic-api", name = "backup-config.resource-type", havingValue = "file", matchIfMissing = true)
|
||||
public MagicBackupService magicFileBackupService() {
|
||||
return new MagicFileBackupService(new File(properties.getBackupConfig().getLocation()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入API调用Service
|
||||
*/
|
||||
@ -538,7 +530,7 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketCon
|
||||
MagicAPIService magicAPIService,
|
||||
MagicNotifyService magicNotifyService,
|
||||
RequestMagicDynamicRegistry requestMagicDynamicRegistry,
|
||||
MagicBackupService magicBackupService) throws NoSuchMethodException {
|
||||
@Autowired(required = false) MagicBackupService magicBackupService) throws NoSuchMethodException {
|
||||
logger.info("magic-api工作目录:{}", magicResource);
|
||||
AsyncCall.setThreadPoolExecutorSize(properties.getThreadPoolExecutorSize());
|
||||
DataType.DATE_PATTERNS = properties.getDatePattern();
|
||||
|
||||
@ -54,7 +54,7 @@ public class MagicConfiguration {
|
||||
|
||||
private MagicBackupService magicBackupService;
|
||||
|
||||
private MagicResourceService magicResourceService;
|
||||
private static MagicResourceService magicResourceService;
|
||||
|
||||
private List<MagicDynamicRegistry<? extends MagicEntity>> magicDynamicRegistries;
|
||||
|
||||
@ -177,12 +177,12 @@ public class MagicConfiguration {
|
||||
this.magicDynamicDataSource = magicDynamicDataSource;
|
||||
}
|
||||
|
||||
public MagicResourceService getMagicResourceService() {
|
||||
return magicResourceService;
|
||||
public static MagicResourceService getMagicResourceService() {
|
||||
return MagicConfiguration.magicResourceService;
|
||||
}
|
||||
|
||||
public void setMagicResourceService(MagicResourceService magicResourceService) {
|
||||
this.magicResourceService = magicResourceService;
|
||||
MagicConfiguration.magicResourceService = magicResourceService;
|
||||
}
|
||||
|
||||
public List<MagicDynamicRegistry<? extends MagicEntity>> getMagicDynamicRegistries() {
|
||||
|
||||
@ -108,11 +108,11 @@ public class RequestHandler extends MagicController {
|
||||
}
|
||||
requestEntity.setHeaders(headers);
|
||||
List<Path> paths = new ArrayList<>(info.getPaths());
|
||||
// MappingHandlerMapping.findGroups(info.getGroupId())
|
||||
// .stream()
|
||||
// .flatMap(it -> it.getPaths().stream())
|
||||
// .filter(it -> !paths.contains(it))
|
||||
// .forEach(paths::add);
|
||||
MagicConfiguration.getMagicResourceService().getGroupsByFileId(info.getId())
|
||||
.stream()
|
||||
.flatMap(it -> it.getPaths().stream())
|
||||
.filter(it -> !paths.contains(it))
|
||||
.forEach(paths::add);
|
||||
Object bodyValue = readRequestBody(requestEntity.getRequest());
|
||||
requestEntity.setRequestBody(bodyValue);
|
||||
String scriptName = requestMagicDynamicRegistry.getMagicResourceStorage().buildScriptName(info);
|
||||
|
||||
@ -2,6 +2,7 @@ package org.ssssssss.magicapi.model;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.ssssssss.magicapi.config.MagicConfiguration;
|
||||
import org.ssssssss.magicapi.utils.JsonUtils;
|
||||
|
||||
import java.util.*;
|
||||
@ -24,7 +25,7 @@ public class ApiInfo extends PathMagicEntity {
|
||||
/**
|
||||
* 设置的接口选项
|
||||
*/
|
||||
private List<Option> option = new ArrayList<>();
|
||||
private List<Option> options = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 请求体
|
||||
@ -128,12 +129,12 @@ public class ApiInfo extends PathMagicEntity {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public List<Option> getOption() {
|
||||
return option;
|
||||
public List<Option> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOption(List<Option> option) {
|
||||
this.option = option;
|
||||
public void setOption(List<Option> options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public List<Parameter> getParameters() {
|
||||
@ -162,28 +163,18 @@ public class ApiInfo extends PathMagicEntity {
|
||||
}
|
||||
|
||||
public String getOptionValue(String key) {
|
||||
if (this.jsonNode == null) {
|
||||
return null;
|
||||
}
|
||||
if (this.jsonNode.isArray()) {
|
||||
for (JsonNode node : this.jsonNode) {
|
||||
if (node.isObject() && Objects.equals(key, node.get("name").asText())) {
|
||||
return node.get("value").asText();
|
||||
}
|
||||
}
|
||||
} else if (this.jsonNode.isObject()) {
|
||||
JsonNode node = this.jsonNode.get(key);
|
||||
if (node != null) {
|
||||
return node.asText();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
// return MagicRequestDynamicMappingRegistry.findGroups(this.groupId)
|
||||
// .stream()
|
||||
// .flatMap(it -> it.getOptions().stream())
|
||||
// .filter(it -> key.equals(it.getName()))
|
||||
// .findFirst()
|
||||
// .map(it -> Objects.toString(it.getValue(), null)).orElse(null);
|
||||
return this.options.stream()
|
||||
.filter(it -> key.equals(it.getName()))
|
||||
.findFirst()
|
||||
.map(it -> Objects.toString(it.getValue(), null))
|
||||
.orElseGet(() -> MagicConfiguration.getMagicResourceService().getGroupsByFileId(this.id)
|
||||
.stream()
|
||||
.flatMap(it -> it.getOptions().stream())
|
||||
.filter(it -> key.equals(it.getName()))
|
||||
.findFirst()
|
||||
.map(it -> Objects.toString(it.getValue(), null)).orElse(null)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public BaseDefinition getRequestBodyDefinition() {
|
||||
@ -222,7 +213,7 @@ public class ApiInfo extends PathMagicEntity {
|
||||
Objects.equals(paths, apiInfo.paths) &&
|
||||
Objects.equals(groupId, apiInfo.groupId) &&
|
||||
Objects.equals(parameters, apiInfo.parameters) &&
|
||||
Objects.equals(option, apiInfo.option) &&
|
||||
Objects.equals(options, apiInfo.options) &&
|
||||
Objects.equals(requestBody, apiInfo.requestBody) &&
|
||||
Objects.equals(headers, apiInfo.headers) &&
|
||||
Objects.equals(description, apiInfo.description) &&
|
||||
@ -233,7 +224,7 @@ public class ApiInfo extends PathMagicEntity {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, method, path, script, name, groupId, parameters, option, requestBody, headers, responseBody, description, requestBodyDefinition, responseBodyDefinition);
|
||||
return Objects.hash(id, method, path, script, name, groupId, parameters, options, requestBody, headers, responseBody, description, requestBodyDefinition, responseBodyDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -34,7 +34,7 @@ public class Backup {
|
||||
/**
|
||||
* 备份内容
|
||||
*/
|
||||
private String content;
|
||||
private byte[] content;
|
||||
|
||||
/**
|
||||
* 操作人,取用户名,空为系统记录
|
||||
@ -45,7 +45,7 @@ public class Backup {
|
||||
public Backup() {
|
||||
}
|
||||
|
||||
public Backup(String id, String type, String name, String content) {
|
||||
public Backup(String id, String type, String name, byte[] content) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
@ -84,11 +84,11 @@ public class Backup {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package org.ssssssss.magicapi.provider;
|
||||
|
||||
import org.ssssssss.magicapi.model.*;
|
||||
import org.ssssssss.magicapi.utils.JsonUtils;
|
||||
import org.ssssssss.magicapi.model.ApiInfo;
|
||||
import org.ssssssss.magicapi.model.Backup;
|
||||
import org.ssssssss.magicapi.model.DataSourceInfo;
|
||||
import org.ssssssss.magicapi.model.FunctionInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -20,7 +22,7 @@ public interface MagicBackupService {
|
||||
* @param apiInfo 接口信息
|
||||
*/
|
||||
default void backup(ApiInfo apiInfo) {
|
||||
doBackup(new Backup(apiInfo.getId(), Constants.PATH_API, apiInfo.getName(), JsonUtils.toJsonString(apiInfo)));
|
||||
// doBackup(new Backup(apiInfo.getId(), Constants.PATH_API, apiInfo.getName(), JsonUtils.toJsonString(apiInfo)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -29,7 +31,7 @@ public interface MagicBackupService {
|
||||
* @param functionInfo 函数信息
|
||||
*/
|
||||
default void backup(FunctionInfo functionInfo) {
|
||||
doBackup(new Backup(functionInfo.getId(), Constants.PATH_FUNCTION, functionInfo.getName(), JsonUtils.toJsonString(functionInfo)));
|
||||
// doBackup(new Backup(functionInfo.getId(), Constants.PATH_FUNCTION, functionInfo.getName(), JsonUtils.toJsonString(functionInfo)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,176 +0,0 @@
|
||||
package org.ssssssss.magicapi.provider.impl;
|
||||
|
||||
import org.ssssssss.magicapi.model.Backup;
|
||||
import org.ssssssss.magicapi.provider.MagicBackupService;
|
||||
import org.ssssssss.magicapi.utils.IoUtils;
|
||||
import org.ssssssss.magicapi.utils.JsonUtils;
|
||||
import org.ssssssss.magicapi.utils.MD5Utils;
|
||||
import org.ssssssss.magicapi.utils.WebUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 文件备份实现
|
||||
*
|
||||
* @author mxd
|
||||
*/
|
||||
public class MagicFileBackupService implements MagicBackupService {
|
||||
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
|
||||
private static final String SUFFIX = ".json";
|
||||
|
||||
/**
|
||||
* 保存路径
|
||||
*/
|
||||
private final File backupDirectory;
|
||||
|
||||
public MagicFileBackupService(File backupDirectory) {
|
||||
this.backupDirectory = backupDirectory;
|
||||
if (!backupDirectory.exists()) {
|
||||
backupDirectory.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBackup(Backup backup) {
|
||||
if (backup.getCreateDate() == 0) {
|
||||
backup.setCreateDate(System.currentTimeMillis());
|
||||
}
|
||||
if (backup.getCreateBy() == null) {
|
||||
backup.setCreateBy(WebUtils.currentUserName());
|
||||
}
|
||||
File directory = new File(backupDirectory, Instant.ofEpochMilli(backup.getCreateDate()).atZone(ZoneOffset.ofHours(8)).toLocalDate().format(FORMATTER));
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
IoUtils.write(new File(directory, getFilename(backup)), JsonUtils.toJsonString(backup));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Backup> backupList(long timestamp) {
|
||||
File[] fileArray = backupDirectory.listFiles();
|
||||
List<Backup> records = new ArrayList<>(FETCH_SIZE);
|
||||
if (fileArray != null) {
|
||||
List<File> dirs = Stream.of(fileArray).sorted(Comparator.comparing(File::getName).reversed()).collect(Collectors.toList());
|
||||
outer:
|
||||
for (File dir : dirs) {
|
||||
fileArray = dir.listFiles((directory, name) -> getTimestampFromFilename(name) < timestamp);
|
||||
if (fileArray != null) {
|
||||
for (File file : fileArray) {
|
||||
records.add(JsonUtils.readValue(IoUtils.string(file), Backup.class));
|
||||
if (records.size() >= FETCH_SIZE) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return records.stream()
|
||||
.sorted(Comparator.comparing(Backup::getCreateDate).reversed())
|
||||
.map(Backup::small)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Backup> backupById(String id) {
|
||||
return backupByFilenameFilter((dir, name) -> name.endsWith(id + SUFFIX))
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(Backup::getCreateDate).reversed())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Backup backupInfo(String id, long timestamp) {
|
||||
File directory = new File(backupDirectory, Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDate().format(FORMATTER));
|
||||
if (directory.exists()) {
|
||||
File[] files = directory.listFiles((dir, name) -> name.startsWith("" + timestamp) && name.endsWith(id + SUFFIX));
|
||||
if (files != null && files.length > 0) {
|
||||
return JsonUtils.readValue(IoUtils.string(files[0]), Backup.class);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Backup> backupByTag(String tag) {
|
||||
String tagId = MD5Utils.encrypt(tag);
|
||||
return backupByFilenameFilter((dir, name) -> name.endsWith(SUFFIX) && name.contains("-" + tagId + "-"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long removeBackup(String id) {
|
||||
return getFilesByFilenameFilter((dir, name) -> name.endsWith(id + SUFFIX))
|
||||
.stream()
|
||||
.filter(File::delete)
|
||||
.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long removeBackup(List<String> idList) {
|
||||
List<String> filenames = idList.stream().map(it -> it + SUFFIX).collect(Collectors.toList());
|
||||
return getFilesByFilenameFilter((dir, name) -> filenames.stream().anyMatch(name::endsWith))
|
||||
.stream()
|
||||
.filter(File::delete)
|
||||
.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long removeBackupByTimestamp(long timestamp) {
|
||||
long count = getFilesByFilenameFilter((dir, name) -> name.contains("-") && name.endsWith(".json") && name.length() == 32 + 32 + 13 + 2 + 5 && getTimestampFromFilename(name) < timestamp)
|
||||
.stream()
|
||||
.filter(File::delete)
|
||||
.count();
|
||||
// 删除空目录
|
||||
File[] files = backupDirectory.listFiles(File::isDirectory);
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
String[] list = file.list();
|
||||
if (list == null || list.length == 0) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private String getFilename(Backup backup) {
|
||||
return String.format("%s-%s-%s.json", backup.getCreateDate(), MD5Utils.encrypt(Objects.toString(backup.getTag(), "")), backup.getId());
|
||||
}
|
||||
|
||||
private Long getTimestampFromFilename(String filename) {
|
||||
return Long.valueOf(filename.substring(0, 13));
|
||||
}
|
||||
|
||||
private List<File> getFilesByFilenameFilter(FilenameFilter filenameFilter) {
|
||||
List<File> list = new ArrayList<>();
|
||||
File[] dirs = backupDirectory.listFiles();
|
||||
if (dirs != null) {
|
||||
for (File dir : dirs) {
|
||||
if (dir.isDirectory()) {
|
||||
File[] files = dir.listFiles(filenameFilter);
|
||||
if (files != null) {
|
||||
list.addAll(Arrays.asList(files));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<Backup> backupByFilenameFilter(FilenameFilter filenameFilter) {
|
||||
return getFilesByFilenameFilter(filenameFilter).stream()
|
||||
.map(IoUtils::string)
|
||||
.map(it -> JsonUtils.readValue(it, Backup.class).small())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@ -45,6 +45,8 @@ public interface MagicResourceService {
|
||||
*/
|
||||
Map<String, TreeNode<Group>> tree();
|
||||
|
||||
List<Group> getGroupsByFileId(String id);
|
||||
|
||||
/**
|
||||
* 获取分组 Resource
|
||||
*
|
||||
|
||||
@ -328,6 +328,22 @@ public class DefaultMagicResourceService implements MagicResourceService, JsonCo
|
||||
return readLock(() -> groupCache.values().stream().collect(Collectors.groupingBy(Group::getType, Collectors.collectingAndThen(Collectors.toList(), this::convertToTree))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> getGroupsByFileId(String id) {
|
||||
return readLock(() -> {
|
||||
List<Group> groups = new ArrayList<>();
|
||||
MagicEntity entity = fileCache.get(id);
|
||||
if (entity != null) {
|
||||
Group group = groupCache.get(entity.getGroupId());
|
||||
while (group != null) {
|
||||
groups.add(group);
|
||||
group = groupCache.get(group.getParentId());
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
});
|
||||
}
|
||||
|
||||
private TreeNode<Group> convertToTree(List<Group> groups) {
|
||||
TreeNode<Group> root = new TreeNode<>();
|
||||
root.setNode(new Group("0", "root"));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user