首页接口重构

This commit is contained in:
2026-04-13 12:46:20 +08:00
parent 2a76f48981
commit adff52a3d7
5 changed files with 147 additions and 245 deletions

View File

@@ -0,0 +1,19 @@
package com.jeesite.modules.apps.Module;
import lombok.Data;
import java.io.Serializable;
@Data
public class DockerInfo implements Serializable {
private String username; // 登录账号
private String password; // 登录密码
private String rootPath; // 初始目录
private String authType; // 认证方式
private String privateKey; // 密钥内容
private String hostIp; // 主机域名
private Integer hostPort; // 主机端口
private String containerId;
public DockerInfo(){}
}

View File

@@ -1,9 +1,98 @@
package com.jeesite.modules.apps.web.docker;
import com.jeesite.modules.apps.Module.ContainerInfo;
import com.jeesite.modules.apps.Module.DockerInfo;
import com.jeesite.modules.apps.Module.DockerResult;
import com.jeesite.modules.biz.dao.MySftpAccountsDao;
import com.jeesite.modules.biz.entity.MySftpAccounts;
import com.jeesite.modules.utils.DockerUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping(value = "${adminPath}/desktop/analysis")
@RequestMapping(value = "${adminPath}/docker/analysis")
public class DockerController {
@Resource
private MySftpAccountsDao mySftpAccountsDao;
/**
* 启动容器
*/
@RequestMapping(value = "start")
@ResponseBody
public DockerResult start(DockerInfo dockerInfo) {
return DockerUtil.start(dockerInfo);
}
/**
* 停止容器
*/
@RequestMapping(value = "stop")
@ResponseBody
public DockerResult stop(DockerInfo dockerInfo) {
return DockerUtil.stop(dockerInfo);
}
/**
* 重启容器
*/
@RequestMapping(value = "restart")
@ResponseBody
public DockerResult restart(DockerInfo dockerInfo) {
return DockerUtil.restart(dockerInfo);
}
/**
* 获取容器详情
*/
@RequestMapping(value = "inspect")
@ResponseBody
public DockerResult inspect(DockerInfo dockerInfo) {
return DockerUtil.inspect(dockerInfo);
}
/**
* 获取容器日志
*/
@RequestMapping(value = "logs")
@ResponseBody
public DockerResult logs(DockerInfo dockerInfo) {
return DockerUtil.getLogs(dockerInfo, 20000, true);
}
/**
* 获取容器列表
*/
@RequestMapping(value = "listAll")
@ResponseBody
public List<ContainerInfo> listAll(DockerInfo dockerInfo) {
return DockerUtil.listContainers(dockerInfo, true);
}
/**
* 获取服务列表
*/
@RequestMapping(value = "listInfo")
@ResponseBody
public List<DockerInfo> listInfo() {
List<MySftpAccounts> accountsList = mySftpAccountsDao.findList(new MySftpAccounts());
return accountsList.stream()
.map(account -> {
DockerInfo info = new DockerInfo();
info.setHostIp(account.getHostIp());
info.setHostPort(account.getHostPort());
info.setUsername(account.getUsername());
info.setPassword(account.getPassword());
info.setRootPath(account.getRootPath());
info.setAuthType(account.getAuthType());
info.setPrivateKey(account.getPrivateKey());
return info;
})
.toList();
}
}

View File

@@ -39,6 +39,14 @@ import java.io.Serial;
@Column(name = "account_remark", attrName = "accountRemark", label = "账号备注"),
@Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true),
@Column(name = "ustatus", attrName = "ustatus", label = "状态"),
}, joinTable = {
@JoinTable(type = Type.LEFT_JOIN, entity = MySftpHosts.class, alias = "b",
on = "a.host_id = b.host_id", attrName = "this",
columns = {
@Column(name = "host_ip", attrName = "hostIp", label = "主机域名"),
@Column(name = "host_port", attrName = "hostPort", label = "主机端口"),
@Column(name = "host_name", attrName = "hostName", label = "主机名称"),
}),
}, orderBy = "a.create_time DESC"
)
@Data
@@ -59,9 +67,9 @@ public class MySftpAccounts extends DataEntity<MySftpAccounts> implements Serial
private Date updateTime; // 更新时间
private String ustatus; // 状态
private String hostIp; // 主机域名
private Integer hostPort; // 主机端口
private String hostName; // 主机名称
private String hostIp; // 主机域名
private Integer hostPort; // 主机端口
private String hostName; // 主机名称
public MySftpAccounts() {
this(null);
@@ -71,116 +79,6 @@ public class MySftpAccounts extends DataEntity<MySftpAccounts> implements Serial
this.hostId = hostId;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public MySftpHosts getHostId() {
return hostId;
}
public void setHostId(MySftpHosts hostId) {
this.hostId = hostId;
}
@NotBlank(message = "登录账号不能为空")
@Size(min = 0, max = 100, message = "登录账号长度不能超过 100 个字符")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@NotBlank(message = "登录密码不能为空")
@Size(min = 0, max = 255, message = "登录密码长度不能超过 255 个字符")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@NotBlank(message = "初始目录不能为空")
@Size(min = 0, max = 255, message = "初始目录长度不能超过 255 个字符")
public String getRootPath() {
return rootPath;
}
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
@NotBlank(message = "认证方式不能为空")
@Size(min = 0, max = 12, message = "认证方式长度不能超过 12 个字符")
public String getAuthType() {
return authType;
}
public void setAuthType(String authType) {
this.authType = authType;
}
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
public Date getExpireTime() {
return expireTime;
}
public void setExpireTime(Date expireTime) {
this.expireTime = expireTime;
}
@Size(min = 0, max = 255, message = "账号备注长度不能超过 255 个字符")
public String getAccountRemark() {
return accountRemark;
}
public void setAccountRemark(String accountRemark) {
this.accountRemark = accountRemark;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@NotBlank(message = "状态不能为空")
@Size(min = 0, max = 12, message = "状态长度不能超过 12 个字符")
public String getUstatus() {
return ustatus;
}
public void setUstatus(String ustatus) {
this.ustatus = ustatus;
}
public Date getCreateTime_gte() {
return sqlMap.getWhere().getValue("create_time", QueryType.GTE);
}

View File

@@ -22,6 +22,7 @@ import com.jeesite.common.utils.excel.annotation.ExcelField.Align;
import com.jeesite.common.utils.excel.annotation.ExcelFields;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import java.io.Serial;
@@ -75,87 +76,9 @@ public class MySftpHosts extends DataEntity<MySftpHosts> implements Serializabl
super(id);
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getHostId() {
return hostId;
}
public void setHostId(String hostId) {
this.hostId = hostId;
}
@NotBlank(message="主机域名不能为空")
@Size(min=0, max=64, message="主机域名长度不能超过 64 个字符")
public String getHostIp() {
return hostIp;
}
public void setHostIp(String hostIp) {
this.hostIp = hostIp;
}
@NotNull(message="主机端口不能为空")
public Integer getHostPort() {
return hostPort;
}
public void setHostPort(Integer hostPort) {
this.hostPort = hostPort;
}
@NotBlank(message="主机名称不能为空")
@Size(min=0, max=100, message="主机名称长度不能超过 100 个字符")
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
@Size(min=0, max=255, message="备注说明长度不能超过 255 个字符")
public String getHostRemark() {
return hostRemark;
}
public void setHostRemark(String hostRemark) {
this.hostRemark = hostRemark;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@NotBlank(message="状态不能为空")
@Size(min=0, max=12, message="状态长度不能超过 12 个字符")
public String getUstatus() {
return ustatus;
}
public void setUstatus(String ustatus) {
this.ustatus = ustatus;
}
@Valid
public List<MySftpAccounts> getMySftpAccountsList() {
return mySftpAccountsList;
}
public void setMySftpAccountsList(List<MySftpAccounts> mySftpAccountsList) {
this.mySftpAccountsList = mySftpAccountsList;
}
}

View File

@@ -2,8 +2,8 @@ package com.jeesite.modules.utils;
import com.jcraft.jsch.*;
import com.jeesite.modules.apps.Module.ContainerInfo;
import com.jeesite.modules.apps.Module.DockerInfo;
import com.jeesite.modules.apps.Module.DockerResult;
import com.jeesite.modules.biz.entity.MySftpAccounts;
import java.io.*;
import java.nio.charset.StandardCharsets;
@@ -20,65 +20,38 @@ public class DockerUtil {
private static final int SSH_TIMEOUT = 30000;
public static DockerResult start(MySftpAccounts account, String image, String name,
String[] ports, String[] envs) {
StringBuilder cmd = new StringBuilder("docker run -d");
if (name != null && !name.isEmpty()) {
cmd.append(" --name ").append(name);
}
if (ports != null) {
for (String p : ports) cmd.append(" -p ").append(p);
}
if (envs != null) {
for (String e : envs) cmd.append(" -e \"").append(e).append("\"");
}
cmd.append(" ").append(image);
return exec(account, cmd.toString());
public static DockerResult start(DockerInfo dockerInfo) {
return exec(dockerInfo, "docker start " + dockerInfo.getContainerId());
}
public static DockerResult stop(MySftpAccounts account, String containerId) {
return exec(account, "docker stop " + containerId);
public static DockerResult stop(DockerInfo dockerInfo) {
return exec(dockerInfo, "docker stop " + dockerInfo.getContainerId());
}
public static DockerResult restart(MySftpAccounts account, String containerId) {
return exec(account, "docker restart " + containerId);
public static DockerResult restart(DockerInfo dockerInfo) {
return exec(dockerInfo, "docker restart " + dockerInfo.getContainerId());
}
public static DockerResult getLogs(MySftpAccounts account, String containerId,
public static DockerResult getLogs(DockerInfo dockerInfo,
int tail, boolean timestamps) {
String cmd = "docker logs" + (timestamps ? " -t" : "")
+ " --tail " + tail + " " + containerId;
return exec(account, cmd);
+ " --tail " + tail + " " + dockerInfo.getContainerId();
return exec(dockerInfo, cmd);
}
public static DockerResult list(MySftpAccounts account, boolean all) {
return exec(account, all ? "docker ps -a" : "docker ps");
public static DockerResult list(DockerInfo dockerInfo, boolean all) {
return exec(dockerInfo, all ? "docker ps -a" : "docker ps");
}
public static DockerResult remove(MySftpAccounts account, String containerId, boolean force) {
String cmd = force
? "docker stop " + containerId + " && docker rm " + containerId
: "docker rm " + containerId;
return exec(account, cmd);
public static DockerResult inspect(DockerInfo dockerInfo) {
return exec(dockerInfo, "docker inspect " + dockerInfo.getContainerId());
}
public static DockerResult inspect(MySftpAccounts account, String containerId) {
return exec(account, "docker inspect " + containerId);
}
public static DockerResult pull(MySftpAccounts account, String image) {
return exec(account, "docker pull " + image);
}
public static DockerResult version(MySftpAccounts account) {
return exec(account, "docker version --format '{{json .}}'");
}
public static List<ContainerInfo> listContainers(MySftpAccounts account, boolean all) {
public static List<ContainerInfo> listContainers(DockerInfo dockerInfo, boolean all) {
List<ContainerInfo> list = new ArrayList<>();
String cmd = (all ? "docker ps -a" : "docker ps")
+ " --format \"{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}\"";
DockerResult r = exec(account, cmd);
DockerResult r = exec(dockerInfo, cmd);
if (!r.isSuccess()) {
return new ArrayList<>();
}
@@ -99,22 +72,22 @@ public class DockerUtil {
return list;
}
public static DockerResult exec(MySftpAccounts account, String command) {
public static DockerResult exec(DockerInfo dockerInfo, String command) {
JSch jsch = new JSch();
Session session = null;
ChannelExec channel = null;
try {
int port = account.getHostPort() != null ? account.getHostPort() : 22;
session = jsch.getSession(account.getUsername(), account.getHostIp(), port);
int port = dockerInfo.getHostPort() != null ? dockerInfo.getHostPort() : 22;
session = jsch.getSession(dockerInfo.getUsername(), dockerInfo.getHostIp(), port);
session.setTimeout(SSH_TIMEOUT);
if ("key".equalsIgnoreCase(account.getAuthType())
&& account.getPrivateKey() != null && !account.getPrivateKey().isEmpty()) {
if ("key".equalsIgnoreCase(dockerInfo.getAuthType())
&& dockerInfo.getPrivateKey() != null && !dockerInfo.getPrivateKey().isEmpty()) {
jsch.addIdentity("temp",
account.getPrivateKey().getBytes(StandardCharsets.UTF_8),
dockerInfo.getPrivateKey().getBytes(StandardCharsets.UTF_8),
null, null);
} else if (account.getPassword() != null && !account.getPassword().isEmpty()) {
session.setPassword(account.getPassword());
} else if (dockerInfo.getPassword() != null && !dockerInfo.getPassword().isEmpty()) {
session.setPassword(dockerInfo.getPassword());
} else {
return DockerResult.fail("SSH 认证信息不完整:缺少密码或私钥");
}
@@ -125,8 +98,8 @@ public class DockerUtil {
session.connect(SSH_TIMEOUT);
channel = (ChannelExec) session.openChannel("exec");
String finalCmd = (account.getRootPath() != null && !account.getRootPath().isEmpty())
? "cd " + account.getRootPath() + " && " + command
String finalCmd = (dockerInfo.getRootPath() != null && !dockerInfo.getRootPath().isEmpty())
? "cd " + dockerInfo.getRootPath() + " && " + command
: command;
channel.setCommand(finalCmd);
channel.setInputStream(null);