1、controller join表排序问题修复

2、优化插件逻辑
This commit is contained in:
ruying408
2024-07-19 05:38:51 +08:00
parent 2e9cf57e3b
commit 81e88bee37
4 changed files with 128 additions and 63 deletions

View File

@@ -18,6 +18,7 @@ import com.cool.modules.plugin.entity.PluginInfoEntity;
import com.cool.modules.plugin.service.PluginInfoService; import com.cool.modules.plugin.service.PluginInfoService;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@@ -25,6 +26,7 @@ import java.nio.file.Paths;
import java.util.List; import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -87,32 +89,22 @@ public class CoolPluginService {
* 安装jar * 安装jar
*/ */
public void install(MultipartFile file, boolean force) { public void install(MultipartFile file, boolean force) {
String fileName;
File jarFile = null; File jarFile = null;
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try { try {
String pathStr = pluginPath; // 保存jar文件
if (!PathUtils.isAbsolutePath(pluginPath)) { jarFile = saveJarFile(file);
// 相对路径 String jarFilePath = jarFile.getAbsolutePath();
pathStr = System.getProperty("user.dir") + File.separator + pluginPath;
}
// 将路径字符串转换为 Path 对象
Path path = Paths.get(pathStr);
// 检查路径是否存在
if (!Files.exists(path)) {
// 如果路径不存在,则创建目录(包括父目录)
Files.createDirectories(path);
}
fileName =
path + File.separator + System.currentTimeMillis() + "_" + file.getOriginalFilename() + ".jar";
jarFile = new File(fileName);
file.transferTo(jarFile);
// 加载jar // 加载jar
PluginJson pluginJson = dynamicJarLoaderService.install(fileName, force); PluginJson pluginJson = dynamicJarLoaderService.install(jarFilePath, force);
// 保存插件信息入库 // 保存插件信息入库
savePluginInfo(pluginJson, fileName, jarFile, force); savePluginInfo(pluginJson, jarFilePath, jarFile, force);
// 把 ApplicationContext 对象传递打插件类中使其在插件中也能正常使用spring bean对象 // 把 ApplicationContext 对象传递打插件类中使其在插件中也能正常使用spring bean对象
CoolPluginInvokers.setApplicationContext(pluginJson.getKey()); CoolPluginInvokers.setApplicationContext(pluginJson.getKey());
} catch (PersistenceException persistenceException) {
// 唯一键冲突
CoolPreconditions.returnData(
new CoolPreconditions.ReturnData(1, "插件已存在,继续安装将覆盖"));
} catch (CoolException e) { } catch (CoolException e) {
FileUtil.del(jarFile); FileUtil.del(jarFile);
throw e; throw e;
@@ -124,6 +116,29 @@ public class CoolPluginService {
} }
} }
/**
* 保存jar文件
*/
private File saveJarFile(MultipartFile file) throws IOException {
String pathStr = pluginPath;
if (!PathUtils.isAbsolutePath(pluginPath)) {
// 相对路径
pathStr = System.getProperty("user.dir") + File.separator + pluginPath;
}
// 将路径字符串转换为 Path 对象
Path path = Paths.get(pathStr);
// 检查路径是否存在
if (!Files.exists(path)) {
// 如果路径不存在,则创建目录(包括父目录)
Files.createDirectories(path);
}
String jarFilePath =
path + File.separator + System.currentTimeMillis() + "_" + file.getOriginalFilename() + ".jar";
File jarFile = new File(jarFilePath);
file.transferTo(jarFile);
return jarFile;
}
/** /**
* 卸载 * 卸载
*/ */
@@ -141,12 +156,76 @@ public class CoolPluginService {
/** /**
* 保存插件信息 * 保存插件信息
*/ */
private void savePluginInfo(PluginJson pluginJson, String fileName, File jarFile, private void savePluginInfo(PluginJson pluginJson, String jarFilePath, File jarFile,
boolean force) { boolean force) {
CoolPreconditions.checkEmpty(pluginJson, "插件安装失败"); CoolPreconditions.checkEmpty(pluginJson, "插件安装失败");
pluginJson.setJarPath(fileName); pluginJson.setJarPath(jarFilePath);
PluginInfoEntity pluginInfo = new PluginInfoEntity(); PluginInfoEntity pluginInfo = new PluginInfoEntity();
BeanUtil.copyProperties(pluginJson, pluginInfo); BeanUtil.copyProperties(pluginJson, pluginInfo);
setLogoOrReadme(pluginJson, pluginInfo);
pluginInfo.setKey(pluginJson.getKey());
pluginInfo.setPluginJson(pluginJson);
// 转二进制
pluginInfo.setJarFile(FileUtil.readBytes(jarFile));
if (force) {
// 判断是否有同名插件, 有将其关闭
closeSameNamePlugin(pluginJson);
// 覆盖插件
coverPlugin(pluginJson, pluginInfo);
return;
}
pluginInfo.save();
}
/**
* 覆盖插件
*/
private void coverPlugin(PluginJson pluginJson, PluginInfoEntity pluginInfo) {
// 通过key 找到id
PluginInfoEntity one = pluginInfoService.getByKeyNoJarFile(pluginJson.getKey());
if (ObjUtil.isNotEmpty(one)) {
// 重新加载配置不更新
pluginInfo.setConfig(one.getConfig());
pluginInfo.getPluginJson().setConfig(one.getConfig());
CopyOptions options = CopyOptions.create().setIgnoreNullValue(true);
BeanUtil.copyProperties(pluginInfo, one, options);
// 忽略为更新的字段
ignoreNoChange(pluginInfo, one);
one.updateById();
}
}
/**
* 关闭同名插件
*/
private void closeSameNamePlugin(PluginJson pluginJson) {
if (ObjUtil.isNotEmpty(pluginJson.getSameHookId())) {
// 存在同名,已强制安装,需将原插件关闭
PluginInfoEntity sameHookPlugin = new PluginInfoEntity();
sameHookPlugin.setStatus(0);
sameHookPlugin.setId(pluginJson.getSameHookId());
updatePlugin(sameHookPlugin);
}
}
/**
* 忽略为更新的字段
*/
private static void ignoreNoChange(PluginInfoEntity pluginInfo, PluginInfoEntity one) {
if (ObjUtil.equals(pluginInfo.getLogo(), one.getLogo())) {
// 头像没变,不更新
one.setLogo(null);
}
if (ObjUtil.equals(pluginInfo.getReadme(), one.getReadme())) {
// readme没变不更新
one.setReadme(null);
}
}
/**
* 设置logo或readme
*/
private void setLogoOrReadme(PluginJson pluginJson, PluginInfoEntity pluginInfo) {
if (ObjUtil.isNotEmpty(pluginJson.getLogo())) { if (ObjUtil.isNotEmpty(pluginJson.getLogo())) {
DynamicJarClassLoader dynamicJarClassLoader = dynamicJarLoaderService DynamicJarClassLoader dynamicJarClassLoader = dynamicJarLoaderService
.getDynamicJarClassLoader(pluginJson.getKey()); .getDynamicJarClassLoader(pluginJson.getKey());
@@ -165,34 +244,6 @@ public class CoolPluginService {
pluginInfo.setReadme(StrUtil.str(IoUtil.readBytes(inputStream), "UTF-8")); pluginInfo.setReadme(StrUtil.str(IoUtil.readBytes(inputStream), "UTF-8"));
} }
} }
pluginInfo.setKey(pluginJson.getKey());
pluginInfo.setPluginJson(pluginJson);
// 转二进制
pluginInfo.setJarFile(FileUtil.readBytes(jarFile));
if (force) {
CopyOptions options = CopyOptions.create().setIgnoreNullValue(true);
if (ObjUtil.isNotEmpty(pluginJson.getSameHookId())) {
// 存在同名,已强制安装,需将原插件关闭
PluginInfoEntity sameHookPlugin = new PluginInfoEntity();
sameHookPlugin.setStatus(0);
sameHookPlugin.setId(pluginJson.getSameHookId());
updatePlugin(sameHookPlugin);
}
// 通过key 找到id
PluginInfoEntity one = pluginInfoService.getByKeyNoJarFile(pluginJson.getKey());
if (ObjUtil.isNotEmpty(one)) {
// 重新加载配置不更新
pluginInfo.setConfig(one.getConfig());
pluginInfo.getPluginJson().setConfig(one.getConfig());
BeanUtil.copyProperties(pluginInfo, one, options);
one.updateById();
// 重新安装了调用设置插件历史配置信息
CoolPluginInvokers.setPluginJson(pluginJson.getKey(), one);
return;
}
}
pluginInfo.save();
} }
public void updatePlugin(PluginInfoEntity entity) { public void updatePlugin(PluginInfoEntity entity) {

View File

@@ -1,15 +1,19 @@
package com.cool.core.request; package com.cool.core.request;
import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.mybatisflex.annotation.Table; import com.mybatisflex.annotation.Table;
import com.mybatisflex.core.query.QueryColumn; import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryCondition; import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import lombok.Data; import lombok.Data;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@@ -31,7 +35,7 @@ public class CrudOption<T> {
public CrudOption(JSONObject requestParams) { public CrudOption(JSONObject requestParams) {
this.requestParams = requestParams; this.requestParams = requestParams;
this.queryWrapper = new QueryWrapper(); this.queryWrapper = QueryWrapper.create();
this.evn = SpringUtil.getBean(Environment.class); this.evn = SpringUtil.getBean(Environment.class);
} }
@@ -72,17 +76,17 @@ public class CrudOption<T> {
} }
Object keyWord = requestParams.get("keyWord"); Object keyWord = requestParams.get("keyWord");
if (ObjectUtil.isNotEmpty(this.keyWordLikeFields) && ObjectUtil.isNotEmpty(keyWord)) { if (ObjectUtil.isNotEmpty(this.keyWordLikeFields) && ObjectUtil.isNotEmpty(keyWord)) {
QueryCondition queryCondition = new QueryCondition(); // 初始化一个空的 QueryCondition
Arrays.stream(keyWordLikeFields).toList().forEach(likeQueryColumn -> { QueryCondition orCondition = null;
if (ObjectUtil.isEmpty(queryCondition.getColumn())) { for (QueryColumn queryColumn : keyWordLikeFields) {
queryCondition.setColumn(likeQueryColumn); QueryCondition condition = queryColumn.like(keyWord);
queryCondition.setLogic(" LIKE "); if (orCondition == null) {
queryCondition.setValue("%" + keyWord + "%"); orCondition = condition;
} else { } else {
queryCondition.or(likeQueryColumn.like(keyWord)); orCondition = orCondition.or(condition);
} }
}); }
queryWrapper.and(queryCondition); queryWrapper.and(orCondition);
} }
if (ObjectUtil.isNotEmpty(select)) { if (ObjectUtil.isNotEmpty(select)) {
queryWrapper.select(select); queryWrapper.select(select);
@@ -98,12 +102,19 @@ public class CrudOption<T> {
// 该对象没有@Table注解非Entity对象 // 该对象没有@Table注解非Entity对象
return; return;
} }
String tableAlias = "";
List<QueryTable> queryTables = (List<QueryTable>) ReflectUtil.getFieldValue(queryWrapper, "queryTables");
if (ObjectUtil.isNotEmpty(queryTables)) {
// 取主表作为排序字段别名
QueryTable queryTable = queryTables.get(0);
tableAlias = "`" + queryTable.getName() + "`.`";
}
String order = requestParams.getStr("order", String order = requestParams.getStr("order",
tableAnnotation.camelToUnderline() ? "create_time" : "createTime"); tableAnnotation.camelToUnderline() ? "create_time" : "createTime");
String sort = requestParams.getStr("sort", "desc"); String sort = requestParams.getStr("sort", "desc");
if (StrUtil.isNotEmpty(order) && StrUtil.isNotEmpty(sort)) { if (StrUtil.isNotEmpty(order) && StrUtil.isNotEmpty(sort)) {
queryWrapper.orderBy( queryWrapper.orderBy(
tableAnnotation.camelToUnderline() ? StrUtil.toUnderlineCase(order) : order, tableAlias + (tableAnnotation.camelToUnderline() ? StrUtil.toUnderlineCase(order) : order) + "`",
sort.equals("asc")); sort.equals("asc"));
} }
} }

View File

@@ -1,5 +1,7 @@
package com.cool.modules.base.controller.admin.sys; package com.cool.modules.base.controller.admin.sys;
import static com.cool.modules.base.entity.sys.table.BaseSysParamEntityTableDef.BASE_SYS_PARAM_ENTITY;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.cool.core.annotation.CoolRestController; import com.cool.core.annotation.CoolRestController;
import com.cool.core.base.BaseController; import com.cool.core.base.BaseController;
@@ -7,9 +9,8 @@ import com.cool.modules.base.entity.sys.BaseSysParamEntity;
import com.cool.modules.base.service.sys.BaseSysParamService; import com.cool.modules.base.service.sys.BaseSysParamService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
/** /**
* 系统参数配置 * 系统参数配置
@@ -20,6 +21,8 @@ public class AdminBaseSysParamController extends BaseController<BaseSysParamServ
@Override @Override
protected void init(HttpServletRequest request, JSONObject requestParams) { protected void init(HttpServletRequest request, JSONObject requestParams) {
setPageOption(createOp().fieldEq(BASE_SYS_PARAM_ENTITY.DATA_TYPE)
.keyWordLikeFields(BASE_SYS_PARAM_ENTITY.NAME, BASE_SYS_PARAM_ENTITY.KEY_NAME));
} }
@Operation(summary = "根据键返回网页的参数值") @Operation(summary = "根据键返回网页的参数值")

View File

@@ -83,7 +83,7 @@ public class BaseSysUserServiceImpl extends BaseServiceImpl<BaseSysUserMapper, B
!coolSecurityUtil.username().equals("admin"))); !coolSecurityUtil.username().equals("admin")));
qw.groupBy(BASE_SYS_USER_ENTITY.ID); qw.groupBy(BASE_SYS_USER_ENTITY.ID);
return mapper.paginateWithRelations(page, qw); return mapper.paginate(page, qw);
} }
@Override @Override