diff --git a/CHANGELOG.md b/CHANGELOG.md index e507f78a0..002d3e3f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,17 @@ ### 新增功能 -1. 控制台日志支持配置报错天数 +1. 控制台日志支持配置保留天数 2. 项目列表状态跟随控制台刷新 3. 项目配置页面优化交互流程 +4. 项目列表显示正在运行的项目的端口号(感谢@洋芋) +5. 新版的Windows管理命令(感谢@洋芋) ### 解决BUG 1. 修改WebHooks 不生效 2. 指定Cookie名称防止名称相同被踢下线(感谢@洋芋) -3. 项目配置页面排版 +3. 优化未加载到tools.jar的提示 ----------------------------------------------------------- diff --git a/src/main/java/cn/keepbx/jpom/common/commander/AbstractCommander.java b/src/main/java/cn/keepbx/jpom/common/commander/AbstractCommander.java index ed1b2bc2e..d173aca98 100644 --- a/src/main/java/cn/keepbx/jpom/common/commander/AbstractCommander.java +++ b/src/main/java/cn/keepbx/jpom/common/commander/AbstractCommander.java @@ -8,7 +8,6 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; -import cn.hutool.system.JavaRuntimeInfo; import cn.hutool.system.OsInfo; import cn.hutool.system.SystemUtil; import cn.jiangzeyin.common.DefaultSystemLog; @@ -17,6 +16,7 @@ import cn.keepbx.jpom.common.commander.impl.WindowsCommander; import cn.keepbx.jpom.model.NetstatModel; import cn.keepbx.jpom.model.ProjectInfoModel; import cn.keepbx.jpom.service.manage.CommandService; +import cn.keepbx.jpom.system.init.CheckPath; import com.sun.tools.attach.*; import sun.management.ConnectorAddressLink; @@ -44,7 +44,6 @@ public abstract class AbstractCommander { private static AbstractCommander abstractCommander = null; protected Charset charset; public static final OsInfo OS_INFO = SystemUtil.getOsInfo(); - private static final JavaRuntimeInfo JAVA_RUNTIME_INFO = SystemUtil.getJavaRuntimeInfo(); protected AbstractCommander(Charset charset) { this.charset = charset; @@ -280,7 +279,7 @@ public abstract class AbstractCommander { if (address != null) { return new JMXServiceURL(address); } - String agent = StrUtil.format("{}{}lib{}management-agent.jar", JAVA_RUNTIME_INFO.getHomeDir(), File.separator, File.separator); + String agent = CheckPath.getManagementAgent(); virtualMachine.loadAgent(agent); address = virtualMachine.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); if (address != null) { diff --git a/src/main/java/cn/keepbx/jpom/controller/manage/ConsoleController.java b/src/main/java/cn/keepbx/jpom/controller/manage/ConsoleController.java index 2996ebbdd..fc3dc78bc 100644 --- a/src/main/java/cn/keepbx/jpom/controller/manage/ConsoleController.java +++ b/src/main/java/cn/keepbx/jpom/controller/manage/ConsoleController.java @@ -1,7 +1,6 @@ package cn.keepbx.jpom.controller.manage; -import cn.hutool.core.io.IoUtil; -import cn.jiangzeyin.common.DefaultSystemLog; +import cn.hutool.extra.servlet.ServletUtil; import cn.jiangzeyin.common.JsonMessage; import cn.keepbx.jpom.common.BaseController; import cn.keepbx.jpom.model.ProjectInfoModel; @@ -16,9 +15,6 @@ import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.OutputStream; /** * 控制台 @@ -63,26 +59,13 @@ public class ConsoleController extends BaseController { @RequestMapping(value = "export.html", method = RequestMethod.GET) @ResponseBody public String export(String id) { - try { - ProjectInfoModel pim = projectInfoService.getItem(id); - File file = new File(pim.getLog()); - if (!file.exists()) { - return JsonMessage.getString(400, "没有日志文件:" + file.getPath()); - } - HttpServletResponse response = getResponse(); - // 设置强制下载不打开 - response.setContentType("application/force-download"); - // 设置文件名 - response.addHeader("Content-Disposition", "attachment;fileName=" + file.getName()); - OutputStream os = response.getOutputStream(); - byte[] bytes = IoUtil.readBytes(new FileInputStream(file)); - IoUtil.write(os, false, bytes); - os.flush(); - os.close(); - return "ok"; - } catch (IOException e) { - DefaultSystemLog.ERROR().error("删除文件异常", e); + ProjectInfoModel pim = projectInfoService.getItem(id); + File file = new File(pim.getLog()); + if (!file.exists()) { + return JsonMessage.getString(400, "没有日志文件:" + file.getPath()); } - return JsonMessage.getString(500, "导出失败"); + HttpServletResponse response = getResponse(); + ServletUtil.write(response, file); + return JsonMessage.getString(200, ""); } } diff --git a/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java b/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java index d81b18162..1829da867 100644 --- a/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java +++ b/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java @@ -129,16 +129,16 @@ public class EditProjectController extends BaseController { } String lib = projectInfo.getLib(); if (StrUtil.isEmpty(lib)) { - return JsonMessage.getString(401, "项目lib不能为空"); + return JsonMessage.getString(401, "项目Jar路径不能为空"); } if (StrUtil.SLASH.equals(lib)) { - return JsonMessage.getString(401, "项目lib不能为顶级目录"); + return JsonMessage.getString(401, "项目Jar路径不能为顶级目录"); } if (Validator.isChinese(lib)) { - return JsonMessage.getString(401, "项目lib中不能包含中文"); + return JsonMessage.getString(401, "项目Jar路径中不能包含中文"); } if (!checkPathSafe(lib)) { - return JsonMessage.getString(401, "项目lib存在提升目录问题"); + return JsonMessage.getString(401, "项目Jar路径存在提升目录问题"); } return null; } @@ -148,11 +148,10 @@ public class EditProjectController extends BaseController { * * @param projectInfo 项目实体 * @return json - * @throws IOException IO */ @RequestMapping(value = "saveProject", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody - public String saveProject(ProjectInfoModel projectInfo, String whitelistDirectory) throws IOException { + public String saveProject(ProjectInfoModel projectInfo, String whitelistDirectory) { String error = checkParameter(projectInfo, whitelistDirectory); if (error != null) { return error; @@ -166,14 +165,14 @@ public class EditProjectController extends BaseController { if (list != null) { for (ProjectInfoModel projectInfoModel : list) { if (!projectInfoModel.getId().equals(id) && projectInfoModel.getLib().equals(lib)) { - return JsonMessage.getString(401, "当前项目lib已经被【" + projectInfoModel.getName() + "】占用,请检查"); + return JsonMessage.getString(401, "当前项目Jar路径已经被【" + projectInfoModel.getName() + "】占用,请检查"); } } } projectInfo.setLib(lib); File checkFile = new File(projectInfo.getLib()); if (checkFile.exists() && checkFile.isFile()) { - return JsonMessage.getString(401, "项目lib是一个已经存在的文件"); + return JsonMessage.getString(401, "项目Jar路径是一个已经存在的文件"); } // 自动生成log文件 String log = new File(lib).getParent(); @@ -189,13 +188,13 @@ public class EditProjectController extends BaseController { return JsonMessage.getString(401, "WebHooks 地址不合法"); } // 判断空格 - if (id.contains(StrUtil.SPACE) || lib.contains(StrUtil.SPACE) || log.contains(StrUtil.SPACE)) { - return JsonMessage.getString(401, "项目Id、项目Lib、WebHooks不能包含空格"); + if (id.contains(StrUtil.SPACE) || lib.contains(StrUtil.SPACE)) { + return JsonMessage.getString(401, "项目Id、项目Jar不能包含空格"); } return save(projectInfo); } - private String save(ProjectInfoModel projectInfo) throws IOException { + private String save(ProjectInfoModel projectInfo) { String edit = getParameter("edit"); ProjectInfoModel exits = projectInfoService.getItem(projectInfo.getId()); try { @@ -266,7 +265,6 @@ public class EditProjectController extends BaseController { * @param id 项目Id * @param newLib 新lib * @return json - * @throws IOException IO */ @RequestMapping(value = "judge_lib.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody @@ -355,7 +353,7 @@ public class EditProjectController extends BaseController { } } if (projectInfoModel1 != null) { - return new JsonMessage(401, "项目lib和【" + projectInfoModel1.getName() + "】项目冲突:" + projectInfoModel1.getLib()); + return new JsonMessage(401, "项目Jar路径和【" + projectInfoModel1.getName() + "】项目冲突:" + projectInfoModel1.getLib()); } return null; } diff --git a/src/main/java/cn/keepbx/jpom/model/BaseJsonModel.java b/src/main/java/cn/keepbx/jpom/model/BaseJsonModel.java new file mode 100644 index 000000000..6f9415488 --- /dev/null +++ b/src/main/java/cn/keepbx/jpom/model/BaseJsonModel.java @@ -0,0 +1,23 @@ +package cn.keepbx.jpom.model; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +import java.io.Serializable; + +/** + * json方法基础类 + * + * @author jiangzeyin + * @date 2019/4/10 + */ +public abstract class BaseJsonModel implements Serializable { + @Override + public String toString() { + return JSON.toJSONString(this); + } + + public JSONObject toJson() { + return (JSONObject) JSONObject.toJSON(this); + } +} diff --git a/src/main/java/cn/keepbx/jpom/model/BaseModel.java b/src/main/java/cn/keepbx/jpom/model/BaseModel.java index 1acd0fe50..6b7506b42 100644 --- a/src/main/java/cn/keepbx/jpom/model/BaseModel.java +++ b/src/main/java/cn/keepbx/jpom/model/BaseModel.java @@ -1,12 +1,12 @@ package cn.keepbx.jpom.model; -import com.alibaba.fastjson.JSON; - /** + * 基础实体(带id) + * * @author jiangzeyin * @date 2019/3/14 */ -public abstract class BaseModel { +public abstract class BaseModel extends BaseJsonModel { private String id; public String getId() { @@ -16,9 +16,4 @@ public abstract class BaseModel { public void setId(String id) { this.id = id; } - - @Override - public String toString() { - return JSON.toJSONString(this); - } } diff --git a/src/main/java/cn/keepbx/jpom/model/CertModel.java b/src/main/java/cn/keepbx/jpom/model/CertModel.java index 7b59654d1..706f2f8ed 100644 --- a/src/main/java/cn/keepbx/jpom/model/CertModel.java +++ b/src/main/java/cn/keepbx/jpom/model/CertModel.java @@ -129,11 +129,6 @@ public class CertModel extends BaseModel { this.effectiveTime = effectiveTime; } - public JSONObject toJson() { - return (JSONObject) JSONObject.toJSON(this); - } - - /** * 解析证书 * diff --git a/src/main/java/cn/keepbx/jpom/model/NetstatModel.java b/src/main/java/cn/keepbx/jpom/model/NetstatModel.java index 3a9181d76..523e178a9 100644 --- a/src/main/java/cn/keepbx/jpom/model/NetstatModel.java +++ b/src/main/java/cn/keepbx/jpom/model/NetstatModel.java @@ -1,10 +1,12 @@ package cn.keepbx.jpom.model; /** + * 网络端口信息实体 + * * @author jiangzeyin * @date 2019/4/10 */ -public class NetstatModel { +public class NetstatModel extends BaseJsonModel { private String protocol; private String receive; private String send; diff --git a/src/main/java/cn/keepbx/jpom/model/ProjectInfoModel.java b/src/main/java/cn/keepbx/jpom/model/ProjectInfoModel.java index 2b9535865..38b24ab75 100644 --- a/src/main/java/cn/keepbx/jpom/model/ProjectInfoModel.java +++ b/src/main/java/cn/keepbx/jpom/model/ProjectInfoModel.java @@ -3,7 +3,6 @@ package cn.keepbx.jpom.model; import cn.hutool.core.util.StrUtil; import cn.jiangzeyin.common.DefaultSystemLog; import cn.keepbx.jpom.common.commander.AbstractCommander; -import com.alibaba.fastjson.JSONObject; import java.io.File; @@ -178,6 +177,12 @@ public class ProjectInfoModel extends BaseModel { return file.getAbsolutePath(); } + /** + * 拼接java 执行的jar路径 + * + * @param projectInfoModel 项目 + * @return classpath 或者 jar + */ public static String getClassPathLib(ProjectInfoModel projectInfoModel) { File fileLib = new File(projectInfoModel.getLib()); File[] files = fileLib.listFiles(); @@ -264,15 +269,6 @@ public class ProjectInfoModel extends BaseModel { this.args = args; } - @Override - public String toString() { - return JSONObject.toJSONString(this); - } - - public JSONObject toJson() { - return (JSONObject) JSONObject.toJSON(this); - } - /** * 运行方式 */ diff --git a/src/main/java/cn/keepbx/jpom/model/ProjectRecoverModel.java b/src/main/java/cn/keepbx/jpom/model/ProjectRecoverModel.java index bb29cafbb..2829c20e6 100644 --- a/src/main/java/cn/keepbx/jpom/model/ProjectRecoverModel.java +++ b/src/main/java/cn/keepbx/jpom/model/ProjectRecoverModel.java @@ -1,7 +1,6 @@ package cn.keepbx.jpom.model; import cn.hutool.core.lang.ObjectId; -import com.alibaba.fastjson.JSONObject; /** * 项目回收记录实体 @@ -54,13 +53,4 @@ public class ProjectRecoverModel extends BaseModel { public void setDelTime(String delTime) { this.delTime = delTime; } - - @Override - public String toString() { - return JSONObject.toJSONString(this); - } - - public JSONObject toJson() { - return (JSONObject) JSONObject.toJSON(this); - } } diff --git a/src/main/java/cn/keepbx/jpom/model/UserModel.java b/src/main/java/cn/keepbx/jpom/model/UserModel.java index 12d2268b0..aed462b3d 100644 --- a/src/main/java/cn/keepbx/jpom/model/UserModel.java +++ b/src/main/java/cn/keepbx/jpom/model/UserModel.java @@ -4,7 +4,6 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.crypto.SecureUtil; import cn.keepbx.jpom.system.ExtConfigBean; import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; import java.util.concurrent.TimeUnit; @@ -268,8 +267,4 @@ public class UserModel extends BaseModel { public boolean isSystemUser() { return UserModel.SYSTEM_ADMIN.equals(getParent()); } - - public JSONObject toJson() { - return (JSONObject) JSONObject.toJSON(this); - } } diff --git a/src/main/java/cn/keepbx/jpom/system/init/CheckPath.java b/src/main/java/cn/keepbx/jpom/system/init/CheckPath.java index 40f1ac064..57a2bf49d 100644 --- a/src/main/java/cn/keepbx/jpom/system/init/CheckPath.java +++ b/src/main/java/cn/keepbx/jpom/system/init/CheckPath.java @@ -3,6 +3,7 @@ package cn.keepbx.jpom.system.init; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.system.JavaRuntimeInfo; import cn.hutool.system.SystemUtil; import cn.jiangzeyin.common.DefaultSystemLog; import cn.jiangzeyin.common.PreLoadClass; @@ -22,6 +23,7 @@ import java.io.IOException; public class CheckPath { private static final String CLASS_NAME = "com.sun.tools.attach.VirtualMachine"; + private static final JavaRuntimeInfo JAVA_RUNTIME_INFO = SystemUtil.getJavaRuntimeInfo(); @PreLoadMethod(1) private static void checkPath() throws IOException { @@ -45,7 +47,11 @@ public class CheckPath { ClassUtil.loadClass(CLASS_NAME, false); } catch (Exception e) { File file = getToolsJar(); - DefaultSystemLog.ERROR().error("当前JDK中没有找到tools.jar,请检查当前JDK是否安装完整,文件完整路径是:" + file.getAbsolutePath(), e); + if (file.exists() && file.isFile()) { + DefaultSystemLog.ERROR().error("Jpom未能正常加载tools.jar,请检查当前系统环境变量是否配置:JAVA_HOME,或者检查Jpom管理命令是否正确", e); + } else { + DefaultSystemLog.ERROR().error("当前JDK中没有找到tools.jar,请检查当前JDK是否安装完整,文件完整路径是:" + file.getAbsolutePath(), e); + } System.exit(-1); } } @@ -54,4 +60,18 @@ public class CheckPath { File file = new File(SystemUtil.getJavaRuntimeInfo().getHomeDir()); return new File(file.getParentFile(), "lib/tools.jar"); } + + /** + * 获取jdk 中agent + * + * @return 路径 + */ + public static String getManagementAgent() { + String agent = StrUtil.format("{}{}lib{}management-agent.jar", JAVA_RUNTIME_INFO.getHomeDir(), File.separator, File.separator); + File file = new File(agent); + if (file.exists() && file.isFile()) { + return agent; + } + throw new RuntimeException("JDK中" + file.getAbsolutePath() + " 文件不存在"); + } }