Commit 02897568 authored by liang.tang's avatar liang.tang
Browse files

magic-api

parents
Pipeline #222 failed with stages
in 0 seconds
package org.ssssssss.magicapi.git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.ssssssss.magicapi.core.resource.FileResource;
import org.ssssssss.magicapi.core.resource.Resource;
import org.ssssssss.magicapi.utils.IoUtils;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* 文件存储实现
*
* @author mxd
*/
public class GitResource extends FileResource {
private final GitRepo gitRepo;
public static GitResource of(org.ssssssss.magicapi.core.config.Resource config, MagicGitProperties properties) throws IOException, GitAPIException {
File file = new File(config.getLocation());
GitRepo gitRepo = new GitRepo(file.getAbsolutePath(), properties);
GitResource gitResource = new GitResource(config.isReadonly(), file,
file.getAbsolutePath(), gitRepo);
// 初始化
gitResource.setup();
return gitResource;
}
public GitResource(boolean readonly, File file, String rootPath, GitRepo gitRepo) {
super(file, readonly, rootPath);
this.gitRepo = gitRepo;
}
/**
* 进行初始化操作, 仅仅在项目启动时进行初始化
* @author soriee
* @date 2022/2/20 22:30
* @return
*/
private void setup() throws IOException, GitAPIException {
synchronized(GitResource.class) {
gitRepo.setupRepo();
}
}
private boolean update(boolean update) {
return gitRepo.update(update);
}
@Override
public boolean delete() {
return super.delete() && this.update(true);
}
@Override
public boolean mkdir() {
return super.mkdir() && this.update(false);
}
@Override
public Resource getResource(String name) {
return new GitResource(super.readonly(), new File(super.file, name), super.rootPath, this.gitRepo);
}
@Override
public Resource getDirectory(String name) {
return getResource(name);
}
@Override
public boolean write(byte[] bytes) {
return super.write(bytes) && this.update(false);
}
@Override
public boolean write(String content) {
return super.write(content) && this.update(false);
}
@Override
public List<Resource> resources() {
File[] files = this.file.listFiles();
return files == null ? Collections.emptyList() : Arrays.stream(files).map(it -> new GitResource(this.readonly(),
it, this.rootPath, this.gitRepo)).collect(Collectors.toList());
}
@Override
public Resource parent() {
return this.rootPath.equals(this.file.getAbsolutePath()) ? null : new GitResource(this.readonly(),
this.file.getParentFile(), this.rootPath, this.gitRepo);
}
@Override
public List<Resource> dirs() {
return IoUtils.dirs(this.file).stream().map(it -> new GitResource(this.readonly(),
it, this.rootPath, this.gitRepo)).collect(Collectors.toList());
}
@Override
public List<Resource> files(String suffix) {
return IoUtils.files(this.file, suffix).stream().map(it -> new GitResource(this.readonly(),
it, this.rootPath, this.gitRepo)).collect(Collectors.toList());
}
@Override
public boolean renameTo(Resource resource) {
if (!this.readonly()) {
File target = ((GitResource) resource).file;
if (this.file.renameTo(target)) {
this.file = target;
// 更新两次,新增文件和删除文件都要更新
this.update(false);
this.update(true);
return true;
}
}
return false;
}
@Override
public String toString() {
return this.gitRepo.getProperties().getUrl();
}
}
package org.ssssssss.magicapi.git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.ssssssss.magicapi.core.config.MagicAPIProperties;
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
import org.ssssssss.magicapi.core.config.Resource;
import org.ssssssss.magicapi.core.model.Plugin;
import java.io.IOException;
@Configuration
@EnableConfigurationProperties(MagicGitProperties.class)
public class MagicGitConfiguration implements MagicPluginConfiguration {
private final MagicAPIProperties properties;
private final MagicGitProperties gitProperties;
public MagicGitConfiguration(MagicAPIProperties properties, MagicGitProperties gitProperties) {
this.properties = properties;
this.gitProperties = gitProperties;
}
/**
* git存储
* @author soriee
* @date 2022/2/28 19:50
* @return
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "magic-api", name = "resource.type", havingValue = "git")
public org.ssssssss.magicapi.core.resource.Resource magicGitResource() throws IOException, GitAPIException {
Resource resourceConfig = properties.getResource();
return GitResource.of(resourceConfig, this.gitProperties);
}
@Override
public Plugin plugin() {
return new Plugin("Git");
}
}
package org.ssssssss.magicapi.git;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "magic-api.resource.git")
public class MagicGitProperties {
/**
* git仓库地址
*/
private String url;
/**
* git分支
*/
private String branch;
/**
* ssh 密钥地址
* 仅支持-m PEM参数生产的ssh key
*/
private String privateKey;
/**
* git账号
*/
private String username;
/**
* git密码
*/
private String password;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.ssssssss.magicapi.git.MagicGitConfiguration
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugins</artifactId>
<version>2.1.1</version>
</parent>
<artifactId>magic-api-plugin-mongo</artifactId>
<packaging>jar</packaging>
<name>magic-api-plugin-mongo</name>
<description>magic-api-plugin-mongo</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
</project>
package org.ssssssss.magicapi.mongo;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
import org.ssssssss.magicapi.core.model.Plugin;
import org.ssssssss.script.reflection.JavaReflection;
@Configuration
public class MagicMongoConfiguration implements MagicPluginConfiguration {
@Override
public Plugin plugin() {
return new Plugin("Mongo");
}
/**
* 注入mongo模块
*/
@Bean
@ConditionalOnMissingBean
public MongoModule mongoFunctions(MongoTemplate mongoTemplate) {
JavaReflection.registerMethodExtension(MongoCollection.class, new MongoCollectionExtension());
JavaReflection.registerMethodExtension(FindIterable.class, new MongoFindIterableExtension());
return new MongoModule(mongoTemplate);
}
@Bean
public MongoFunction mongoFunction(){
return new MongoFunction();
}
}
package org.ssssssss.magicapi.mongo;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.UpdateOptions;
import org.bson.Document;
import org.ssssssss.script.annotation.Comment;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* MongoCollection方法扩展
*
* @author mxd
*/
public class MongoCollectionExtension {
@Comment("执行批量插入操作")
public void insert(MongoCollection<Document> collection,
@Comment(name = "maps", value = "要插入的集合") List<Map<String, Object>> maps) {
collection.insertMany(maps.stream().map(Document::new).collect(Collectors.toList()));
}
@Comment("执行单条插入操作")
public void insert(MongoCollection<Document> collection,
@Comment(name = "map", value = "执行插入数据") Map<String, Object> map) {
insert(collection, Collections.singletonList(map));
}
@Comment("执行查询操作")
public FindIterable<Document> find(MongoCollection<Document> collection,
@Comment(name = "query", value = "查询条件") Map<String, Object> query) {
return collection.find(new Document(query));
}
@Comment("修改操作,返回修改数量")
public long update(MongoCollection<Document> collection,
@Comment(name = "query", value = "查询条件") Map<String, Object> query,
@Comment(name = "update", value = "修改值") Map<String, Object> update) {
return collection.updateOne(new Document(query), new Document(update)).getModifiedCount();
}
@Comment("批量修改,返回修改数量")
public long updateMany(MongoCollection<Document> collection,
@Comment(name = "query", value = "修改条件") Map<String, Object> query,
@Comment(name = "update", value = "修改值") Map<String, Object> update) {
return collection.updateMany(new Document(query), new Document(update)).getModifiedCount();
}
@Comment("批量修改,返回修改数量")
public long updateMany(MongoCollection<Document> collection,
@Comment(name = "query", value = "查询条件") Map<String, Object> query,
@Comment(name = "update", value = "修改值") Map<String, Object> update,
@Comment(name = "filters", value = "过滤条件") Map<String, Object> filters) {
UpdateOptions updateOptions = new UpdateOptions();
if (filters != null && !filters.isEmpty()) {
Object upsert = filters.get("upsert");
if (upsert != null) {
filters.remove("upsert");
updateOptions.upsert(Boolean.parseBoolean(upsert.toString()));
}
Object bypassDocumentValidation = filters.get("bypassDocumentValidation");
if (bypassDocumentValidation != null) {
filters.remove("bypassDocumentValidation");
updateOptions.bypassDocumentValidation(Boolean.parseBoolean(bypassDocumentValidation.toString()));
}
List<Document> arrayFilters = filters.entrySet().stream().map(entry -> new Document(entry.getKey(), entry.getValue())).collect(Collectors.toList());
updateOptions.arrayFilters(arrayFilters);
}
return collection.updateMany(new Document(query), new Document(update), updateOptions).getModifiedCount();
}
@Comment("查询数量")
public long count(MongoCollection<Document> collection,
@Comment(name = "query", value = "查询") Map<String, Object> query) {
return collection.countDocuments(new Document(query));
}
@Comment("批量删除,返回删除条数")
public long remove(MongoCollection<Document> collection,
@Comment(name = "query", value = "删除条件") Map<String, Object> query) {
return collection.deleteMany(new Document(query)).getDeletedCount();
}
@Comment("删除一条,返回删除条数")
public long removeOne(MongoCollection<Document> collection,
@Comment(name = "query", value = "删除条件") Map<String, Object> query) {
return collection.deleteOne(new Document(query)).getDeletedCount();
}
}
package org.ssssssss.magicapi.mongo;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCursor;
import org.bson.Document;
import org.ssssssss.script.annotation.Comment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Mongo FindIterable 方法扩展
*
* @author mxd
*/
public class MongoFindIterableExtension {
@Comment("结果转为List")
public List<Map<String, Object>> list(FindIterable<Document> iterable) {
MongoCursor<Document> cursor = iterable.iterator();
List<Map<String, Object>> result = new ArrayList<>();
while (cursor.hasNext()) {
result.add(cursor.next());
}
return result;
}
}
package org.ssssssss.magicapi.mongo;
import org.bson.types.ObjectId;
import org.ssssssss.magicapi.core.config.MagicFunction;
import org.ssssssss.script.annotation.Comment;
import org.ssssssss.script.annotation.Function;
import java.util.Date;
public class MongoFunction implements MagicFunction {
@Comment("创建ObjectId")
@Function
public ObjectId ObjectId(String hexString){
return new ObjectId(hexString);
}
@Comment("创建ObjectId")
@Function
public ObjectId ObjectId(){
return new ObjectId();
}
@Comment("创建ObjectId")
@Function
public ObjectId ObjectId(byte[] bytes){
return new ObjectId(bytes);
}
@Comment("创建ObjectId")
@Function
public ObjectId ObjectId(Date date){
return new ObjectId(date);
}
}
package org.ssssssss.magicapi.mongo;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.ssssssss.magicapi.core.config.Constants;
import org.ssssssss.magicapi.core.annotation.MagicModule;
import org.ssssssss.script.annotation.Comment;
import org.ssssssss.script.convert.ClassImplicitConvert;
import org.ssssssss.script.functions.DynamicAttribute;
import org.ssssssss.script.reflection.JavaInvoker;
import org.ssssssss.script.reflection.JavaReflection;
import org.ssssssss.script.runtime.Variables;
import java.beans.Transient;
import java.lang.reflect.Method;
import java.util.Map;
/**
* mongo模块
*
* @author mxd
*/
@MagicModule("mongo")
public class MongoModule implements ClassImplicitConvert, DynamicAttribute<MongoModule.MongoDataBaseGetter, MongoModule.MongoDataBaseGetter> {
private static final Logger logger = LoggerFactory.getLogger(MongoModule.class);
private JavaInvoker<Method> invoker;
private Object factory;
public MongoModule(MongoTemplate mongoTemplate) {
JavaInvoker<Method> mongoDbFactoryInvoker = JavaReflection.getMethod(mongoTemplate, "getMongoDbFactory");
if(mongoDbFactoryInvoker == null){
mongoDbFactoryInvoker = JavaReflection.getMethod(mongoTemplate, "getMongoDatabaseFactory");
}
if (mongoDbFactoryInvoker != null) {
try {
factory = mongoDbFactoryInvoker.invoke0(mongoTemplate, null, Constants.EMPTY_OBJECT_ARRAY);
invoker = JavaReflection.getMethod(factory, "getDb", StringUtils.EMPTY);
if (invoker == null) {
invoker = JavaReflection.getMethod(factory, "getMongoDatabase", StringUtils.EMPTY);
}
} catch (Throwable e) {
logger.error("mongo模块初始化失败", e);
}
} else {
logger.error("mongo模块初始化失败");
}
JavaReflection.registerImplicitConvert(this);
}
@Comment("获取`database`")
public MongoDataBaseGetter database(String databaseName){
return getDynamicAttribute(databaseName);
}
@Override
@Transient
public MongoDataBaseGetter getDynamicAttribute(String databaseName) {
try {
if (databaseName == null) {
return null;
}
MongoDatabase database = (MongoDatabase) invoker.invoke0(factory, null, new Object[]{databaseName});
return new MongoDataBaseGetter(database);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public boolean support(Class<?> from, Class<?> to) {
return Map.class.isAssignableFrom(from) && (Bson.class.isAssignableFrom(to));
}
@Override
public Object convert(Variables variables, Object source, Class<?> target) {
return new Document((Map<String, Object>) source);
}
public static class MongoDataBaseGetter implements DynamicAttribute<MongoCollection<Document>, MongoCollection<Document>> {
MongoDatabase database;
public MongoDataBaseGetter(MongoDatabase database) {
this.database = database;
}
@Override
@Transient
public MongoCollection<Document> getDynamicAttribute(String key) {
return database.getCollection(key);
}
@Comment("获取`Collection`")
public MongoCollection<Document> collection(String key){
return getDynamicAttribute(key);
}
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.ssssssss.magicapi.mongo.MagicMongoConfiguration
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugins</artifactId>
<version>2.1.1</version>
</parent>
<artifactId>magic-api-plugin-redis</artifactId>
<packaging>jar</packaging>
<name>magic-api-plugin-redis</name>
<description>magic-api-plugin-redis</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
</project>
package org.ssssssss.magicapi.redis;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.ssssssss.magicapi.core.config.MagicAPIProperties;
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
import org.ssssssss.magicapi.core.config.Resource;
import org.ssssssss.magicapi.core.model.Plugin;
@Configuration
public class MagicRedisConfiguration implements MagicPluginConfiguration {
private final MagicAPIProperties properties;
public MagicRedisConfiguration(MagicAPIProperties properties) {
this.properties = properties;
}
/**
* 使用Redis存储
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "magic-api", name = "resource.type", havingValue = "redis")
public org.ssssssss.magicapi.core.resource.Resource magicRedisResource(RedisConnectionFactory connectionFactory) {
Resource resource = properties.getResource();
return new RedisResource(new StringRedisTemplate(connectionFactory), resource.getPrefix(), resource.isReadonly());
}
/**
* 注入redis模块
*/
@Bean
public RedisModule redisFunctions(RedisConnectionFactory connectionFactory) {
return new RedisModule(connectionFactory);
}
@Override
public Plugin plugin() {
return new Plugin("Redis");
}
}
package org.ssssssss.magicapi.redis;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPipelineException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.ReflectionUtils;
import org.ssssssss.magicapi.core.annotation.MagicModule;
import org.ssssssss.script.functions.DynamicMethod;
import org.ssssssss.script.reflection.JavaReflection;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* redis模块
*
* @author mxd
*/
@MagicModule("redis")
public class RedisModule implements DynamicMethod {
private final StringRedisTemplate redisTemplate;
private final boolean isRedisson;
public RedisModule(RedisConnectionFactory connectionFactory) {
this.redisTemplate = new StringRedisTemplate(connectionFactory);
this.isRedisson = Objects.equals("org.redisson.spring.data.connection.RedissonConnectionFactory", this.redisTemplate.getConnectionFactory().getClass().getName());
}
/**
* 序列化
*/
private byte[] serializer(Object value) {
if (value == null || value instanceof String) {
return redisTemplate.getStringSerializer().serialize((String) value);
}
return serializer(value.toString());
}
private Object serializerForRedisson(Object value){
if(value == null || JavaReflection.isPrimitiveAssignableFrom(value.getClass(), value.getClass())){
return value;
}
return serializer(value.toString());
}
/**
* 反序列化
*/
@SuppressWarnings("unchecked")
private Object deserialize(Object value) {
if (value != null) {
if (value instanceof byte[]) {
return this.redisTemplate.getStringSerializer().deserialize((byte[]) value);
}
if (value instanceof List) {
List<Object> valueList = (List<Object>) value;
List<Object> resultList = new ArrayList<>(valueList.size());
for (Object val : valueList) {
resultList.add(deserialize(val));
}
return resultList;
}
if (value instanceof Map) {
Map<Object, Object> map = (Map<Object, Object>) value;
LinkedHashMap<Object, Object> newMap = new LinkedHashMap<>(map.size());
map.forEach((key, val) -> newMap.put(deserialize(key), deserialize(val)));
return newMap;
}
}
return value;
}
/**
* 执行命令
*
* @param methodName 命令名称
* @param parameters 命令参数
*/
@Override
public Object execute(String methodName, List<Object> parameters) {
return this.redisTemplate.execute(connection -> {
Object result;
if(isRedisson){
result = executeForRedisson(((DefaultStringRedisConnection) connection).getDelegate(), methodName, parameters);
} else {
byte[][] params = new byte[parameters.size()][];
for (int i = 0; i < params.length; i++) {
params[i] = serializer(parameters.get(i));
}
result = connection.execute(methodName, params);
}
return deserialize(result);
}, isRedisson || this.redisTemplate.isExposeConnection());
}
private Object executeForRedisson(RedisConnection connection, String command, List<Object> parameters) {
Method[] methods = connection.getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equalsIgnoreCase(command) && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == parameters.size()) {
try {
Object ret = this.execute(connection, method, parameters);
if (ret instanceof String) {
return ((String) ret).getBytes();
}
return ret;
} catch (IllegalArgumentException e) {
if (connection.isPipelined()) {
throw new RedisPipelineException(e);
}
throw new InvalidDataAccessApiUsageException(e.getMessage(), e);
}
}
}
throw new UnsupportedOperationException();
}
private Object execute(RedisConnection connection,Method method, List<Object> parameters){
if (method.getParameterTypes().length > 0 && method.getParameterTypes()[0] == byte[][].class) {
return ReflectionUtils.invokeMethod(method, connection, parameters.stream().map(this::serializer).toArray(byte[][]::new));
} else if (parameters.size() == 0){
return ReflectionUtils.invokeMethod(method, connection);
}
return ReflectionUtils.invokeMethod(method, connection, parameters.stream().map(this::serializerForRedisson).toArray());
}
}
package org.ssssssss.magicapi.redis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.ssssssss.magicapi.core.resource.KeyValueResource;
import org.ssssssss.magicapi.core.resource.Resource;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
/**
* Redis 资源存储实现
*
* @author mxd
*/
public class RedisResource extends KeyValueResource {
private static final Logger logger = LoggerFactory.getLogger(RedisResource.class);
private final StringRedisTemplate redisTemplate;
private final Map<String, String> cachedContent = new ConcurrentHashMap<>();
public RedisResource(StringRedisTemplate redisTemplate, String path, boolean readonly, RedisResource parent) {
super(":", path, readonly, parent);
this.redisTemplate = redisTemplate;
}
public RedisResource(StringRedisTemplate redisTemplate, String path, boolean readonly) {
this(redisTemplate, path, readonly, null);
}
@Override
public void readAll() {
List<String> keys = new ArrayList<>(keys());
List<String> values = redisTemplate.opsForValue().multiGet(keys);
this.cachedContent.entrySet().removeIf(entry -> entry.getKey().startsWith(path));
if (values != null) {
for (int i = 0, size = keys.size(); i < size; i++) {
this.cachedContent.put(keys.get(i), values.get(i));
}
}
}
@Override
public byte[] read() {
String value = this.cachedContent.get(path);
if (value == null) {
value = redisTemplate.opsForValue().get(path);
if (value != null) {
this.cachedContent.put(path, value);
}
}
return value == null ? new byte[0] : value.getBytes(StandardCharsets.UTF_8);
}
@Override
public boolean write(String content) {
this.redisTemplate.opsForValue().set(this.path, content);
this.cachedContent.put(this.path, content);
return true;
}
@Override
protected boolean renameTo(Map<String, String> renameKeys) {
renameKeys.forEach(this.redisTemplate::rename);
renameKeys.forEach((oldKey, newKey) -> this.cachedContent.put(newKey, this.cachedContent.remove(oldKey)));
return true;
}
@Override
public boolean exists() {
if (this.cachedContent.get(this.path) != null) {
return true;
}
return Boolean.TRUE.equals(this.redisTemplate.hasKey(this.path));
}
@Override
protected boolean deleteByKey(String key) {
if (Boolean.TRUE.equals(this.redisTemplate.delete(key))) {
this.cachedContent.remove(key);
return true;
}
return false;
}
@Override
protected Function<String, Resource> mappedFunction() {
return (it) -> new RedisResource(this.redisTemplate, it, readonly, this);
}
@Override
protected Set<String> keys() {
Set<String> keys = this.redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
ScanOptions options = ScanOptions.scanOptions()
.count(Long.MAX_VALUE)
.match((isDirectory() ? this.path : (this.path + separator)) + "*")
.build();
Set<String> returnKeys = new HashSet<>();
try (Cursor<byte[]> cursor = connection.scan(options)) {
while (cursor.hasNext()) {
returnKeys.add(new String(cursor.next()));
}
} catch (Exception e) {
logger.error("扫描key出错", e);
}
return returnKeys;
});
return keys == null ? Collections.emptySet() : keys;
}
@Override
public String toString() {
return String.format("redis://%s", getAbsolutePath());
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.ssssssss.magicapi.redis.MagicRedisConfiguration
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugins</artifactId>
<version>2.1.1</version>
</parent>
<artifactId>magic-api-plugin-springdoc</artifactId>
<packaging>jar</packaging>
<name>magic-api-plugin-springdoc</name>
<description>magic-api-plugin-springdoc</description>
<properties>
<springdoc.version>2.0.4</springdoc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment