From eb7948d5c1c3207f4f270f49abbba554bd949b61 Mon Sep 17 00:00:00 2001 From: "1437892690@qq.com" <1437892690@qq.com> Date: Wed, 2 Jul 2025 14:57:51 +0800 Subject: [PATCH] =?UTF-8?q?[=E5=8A=9F=E8=83=BD]=20=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=E5=92=8C=E4=B8=8B=E8=BD=BD=E6=97=A5=E5=BF=97=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 关联 #[1444848047980544]查看和下载日志页面 http://192.168.0.96:8090/demo/rdm.html#/story-detail/939050947543040/939050947543042/1444848047980544 --- .../tenant/api/log/ExportLogFileApi.java | 143 +++++++++++ .../tenant/api/log/GetLogContentApi.java | 228 ++++++++++++++++++ .../tenant/api/log/GetLogFileNameListApi.java | 162 +++++++++++++ .../tenant/api/server/GetServerListApi.java | 21 +- 4 files changed, 552 insertions(+), 2 deletions(-) create mode 100644 src/main/java/neatlogic/module/tenant/api/log/ExportLogFileApi.java create mode 100644 src/main/java/neatlogic/module/tenant/api/log/GetLogContentApi.java create mode 100644 src/main/java/neatlogic/module/tenant/api/log/GetLogFileNameListApi.java diff --git a/src/main/java/neatlogic/module/tenant/api/log/ExportLogFileApi.java b/src/main/java/neatlogic/module/tenant/api/log/ExportLogFileApi.java new file mode 100644 index 00000000..d4d32d63 --- /dev/null +++ b/src/main/java/neatlogic/module/tenant/api/log/ExportLogFileApi.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package neatlogic.module.tenant.api.log; + +import com.alibaba.fastjson.JSONObject; +import neatlogic.framework.auth.core.AuthAction; +import neatlogic.framework.auth.label.ADMIN; +import neatlogic.framework.common.config.Config; +import neatlogic.framework.common.constvalue.ApiParamType; +import neatlogic.framework.common.util.FileUtil; +import neatlogic.framework.constvalue.SystemProperty; +import neatlogic.framework.exception.SystemPropertyNotFoundException; +import neatlogic.framework.exception.core.ApiRuntimeException; +import neatlogic.framework.exception.file.FileNotFoundException; +import neatlogic.framework.exception.server.ServerHostIsBankException; +import neatlogic.framework.exception.server.ServerNotFoundException; +import neatlogic.framework.heartbeat.dao.mapper.ServerMapper; +import neatlogic.framework.heartbeat.dto.ServerClusterVo; +import neatlogic.framework.integration.authentication.enums.AuthenticateType; +import neatlogic.framework.restful.annotation.Description; +import neatlogic.framework.restful.annotation.Input; +import neatlogic.framework.restful.annotation.OperationType; +import neatlogic.framework.restful.annotation.Param; +import neatlogic.framework.restful.constvalue.OperationTypeEnum; +import neatlogic.framework.restful.core.privateapi.PrivateBinaryStreamApiComponentBase; +import neatlogic.framework.util.HttpRequestUtil; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.InputStream; +import java.util.LinkedHashMap; +import java.util.Objects; + +@Service +@AuthAction(action = ADMIN.class) +@OperationType(type = OperationTypeEnum.SEARCH) +public class ExportLogFileApi extends PrivateBinaryStreamApiComponentBase { + + @Resource + private ServerMapper serverMapper; + + @Override + public String getName() { + return "nmtal.exportlogfileapi.getname"; + } + + @Override + public String getConfig() { + return null; + } + + @Input({ + @Param(name = "serverId", type = ApiParamType.INTEGER, isRequired = true, desc = "term.framework.serverid"), + @Param(name = "fileName", type = ApiParamType.STRING, isRequired = true, desc = "common.path"), + }) + @Description(desc = "nmtal.exportlogfileapi.getname") + @Override + public Object myDoService(JSONObject paramObj, HttpServletRequest request, HttpServletResponse response) throws Exception { + JSONObject resultObj = new JSONObject(new LinkedHashMap<>()); + Integer serverId = paramObj.getInteger("serverId"); + if (Objects.equals(serverId, Config.SCHEDULE_SERVER_ID)) { + String log4jHome = System.getProperties().getProperty(SystemProperty.LOG4J_HOME); + if (log4jHome != null) { + String fileName = paramObj.getString("fileName"); + String path = log4jHome + File.separator + fileName; + File file = new File(path); + if (file.exists()) { + if (file.isFile()) { + if (!path.startsWith("file:")) { + path = "file:" + path; + } + try (InputStream in = FileUtil.getData(path); ) { + if (in != null) { + try (ServletOutputStream os = response.getOutputStream()) { + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", " attachment; filename=\"" + neatlogic.framework.util.FileUtil.getEncodedFileName(fileName) + "\""); + IOUtils.copyLarge(in, os); + os.flush(); + } + } + } + } else { + throw new FileNotFoundException(FileNotFoundException.Type.DIRECTORY, log4jHome); + } + } else { + throw new FileNotFoundException(FileNotFoundException.Type.NONEXISTENT, log4jHome); + } + } else { + throw new SystemPropertyNotFoundException(SystemProperty.LOG4J_HOME); + } + } else { + ServerClusterVo serverClusterVo = serverMapper.getServerByServerId(serverId); + if (serverClusterVo != null) { + String host = serverClusterVo.getHost(); + if (StringUtils.isNotBlank(host)) { + ServletOutputStream os = response.getOutputStream(); + String url = host + request.getRequestURI(); + HttpRequestUtil httpRequestUtil = HttpRequestUtil.download(url, "POST", os) + .setPayload(paramObj.toJSONString()) + .setAuthType(AuthenticateType.BUILDIN) + .setConnectTimeout(5000) + .setReadTimeout(5000) + .sendRequest(); + String error = httpRequestUtil.getError(); + if (StringUtils.isNotBlank(error)) { + throw new ApiRuntimeException(error); + } + } else { + throw new ServerHostIsBankException(serverId); + } + } else { + throw new ServerNotFoundException(serverId); + } + } + return resultObj; + } + + @Override + public String getToken() { + return "log/file/export"; + } +} diff --git a/src/main/java/neatlogic/module/tenant/api/log/GetLogContentApi.java b/src/main/java/neatlogic/module/tenant/api/log/GetLogContentApi.java new file mode 100644 index 00000000..addc8cca --- /dev/null +++ b/src/main/java/neatlogic/module/tenant/api/log/GetLogContentApi.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package neatlogic.module.tenant.api.log; + +import com.alibaba.fastjson.JSONObject; +import neatlogic.framework.asynchronization.threadlocal.RequestContext; +import neatlogic.framework.auth.core.AuthAction; +import neatlogic.framework.auth.label.ADMIN; +import neatlogic.framework.common.config.Config; +import neatlogic.framework.common.constvalue.ApiParamType; +import neatlogic.framework.constvalue.SystemProperty; +import neatlogic.framework.exception.SystemPropertyNotFoundException; +import neatlogic.framework.exception.core.ApiRuntimeException; +import neatlogic.framework.exception.file.FileNotFoundException; +import neatlogic.framework.exception.server.ServerHostIsBankException; +import neatlogic.framework.exception.server.ServerNotFoundException; +import neatlogic.framework.heartbeat.dao.mapper.ServerMapper; +import neatlogic.framework.heartbeat.dto.ServerClusterVo; +import neatlogic.framework.integration.authentication.enums.AuthenticateType; +import neatlogic.framework.restful.annotation.*; +import neatlogic.framework.restful.constvalue.OperationTypeEnum; +import neatlogic.framework.restful.core.privateapi.PrivateApiComponentBase; +import neatlogic.framework.util.HttpRequestUtil; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Objects; + +import static com.alibaba.fastjson.util.IOUtils.UTF8; + +@AuthAction(action = ADMIN.class) +@Service +@OperationType(type = OperationTypeEnum.SEARCH) +public class GetLogContentApi extends PrivateApiComponentBase { + + private final int DEFAULT_BUFFER_SIZE = 8192; // 8KB缓冲区 + // 读取最大行数 + private final int DEFAULT_MAX_LINES = 1000; + // 读取最大字节数 + private final int DEFAULT_MAX_BYTES = 200 * DEFAULT_MAX_LINES; + + @Resource + private ServerMapper serverMapper; + + @Override + public String getName() { + return "nmtal.getlogcontentapi.getname"; + } + + @Input({ + @Param(name = "serverId", type = ApiParamType.INTEGER, isRequired = true, desc = "term.framework.serverid"), + @Param(name = "fileName", type = ApiParamType.STRING, isRequired = true, desc = "common.filename"), + @Param(name = "fileSize", type = ApiParamType.LONG, desc = "common.filesize") + }) + @Output({ + @Param(name = "Return", type = ApiParamType.STRING, desc = "common.tbodylist") + }) + @Description(desc = "nmtal.getlogcontentapi.getname") + @Override + public Object myDoService(JSONObject paramObj) throws Exception { + JSONObject resultObj = new JSONObject(); + Integer serverId = paramObj.getInteger("serverId"); + if (Objects.equals(serverId, Config.SCHEDULE_SERVER_ID)) { + String fileName = paramObj.getString("fileName"); + String log4jHome = System.getProperties().getProperty(SystemProperty.LOG4J_HOME); + if (log4jHome != null) { + File file = new File(log4jHome + File.separator + fileName); + if (file.exists()) { + if (file.isFile()) { + long length = file.length(); + Long fileSize = paramObj.getLong("fileSize"); + if (!Objects.equals(fileSize, length)) { + StringBuilder stringBuilder = readLastLines(file, DEFAULT_MAX_LINES, DEFAULT_MAX_BYTES); + resultObj.put("content", stringBuilder.toString()); + resultObj.put("isRefresh", 1); + } else { + resultObj.put("isRefresh", 0); + } + resultObj.put("fileSize", length); + resultObj.put("filePath", file.getAbsolutePath()); + return resultObj; + } else { + throw new FileNotFoundException(FileNotFoundException.Type.DIRECTORY, log4jHome); + } + } else { + throw new FileNotFoundException(FileNotFoundException.Type.NONEXISTENT, log4jHome); + } + } else { + throw new SystemPropertyNotFoundException(SystemProperty.LOG4J_HOME); + } + } else { + ServerClusterVo serverClusterVo = serverMapper.getServerByServerId(serverId); + if (serverClusterVo != null) { + String host = serverClusterVo.getHost(); + if (StringUtils.isNotBlank(host)) { + HttpServletRequest request = RequestContext.get().getRequest(); + String url = host + request.getRequestURI(); + HttpRequestUtil httpRequestUtil = HttpRequestUtil.post(url) + .setPayload(paramObj.toJSONString()) + .setAuthType(AuthenticateType.BUILDIN) + .setConnectTimeout(5000) + .setReadTimeout(5000) + .sendRequest(); + String error = httpRequestUtil.getError(); + if (StringUtils.isNotBlank(error)) { + throw new ApiRuntimeException(error); + } + JSONObject resultJson = httpRequestUtil.getResultJson(); + if (MapUtils.isNotEmpty(resultJson)) { + String status = resultJson.getString("Status"); + if (!"OK".equals(status)) { + throw new RuntimeException(resultJson.getString("Message")); + } + resultObj = resultJson.getJSONObject("Return"); + } + } else { + throw new ServerHostIsBankException(serverId); + } + } else { + throw new ServerNotFoundException(serverId); + } + return resultObj; + } + } + + @Override + public String getToken() { + return "log/content/get"; + } + + /** + * 读取文件最后几行 + * @param file + * @param maxLines 最大行数 + * @param maxChars 最大字符数 + * @return + * @throws IOException + */ + private StringBuilder readLastLines(File file, int maxLines, int maxChars) throws IOException { + StringBuilder result = new StringBuilder(); + try (FileChannel channel = FileChannel.open(Paths.get(file.toURI()), StandardOpenOption.READ)) { + long fileSize = channel.size(); + // 分配堆内存缓冲区(JVM堆内) + ByteBuffer buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE); + CharBuffer charBuffer = CharBuffer.allocate(DEFAULT_BUFFER_SIZE); + CharsetDecoder decoder = UTF8.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + long position = fileSize; + // 已读取行数 + int linesFound = 0; + // 已读取字符数 + int charsRead = 0; + while (position > 0 && linesFound <= maxLines && charsRead <= maxChars) { + // 计算本次读取的起始位置和大小 + int readSize = (int) Math.min(DEFAULT_BUFFER_SIZE, position); + position -= readSize; + // 清空缓冲区(准备重新写入) + buffer.clear(); + // 设置当前读写位置 + channel.position(position); + // 读取数据到缓冲区 + channel.read(buffer); + // 切换为读取模式 + buffer.flip(); + // 解码字节到字符 + decoder.reset(); + charBuffer.clear(); + decoder.decode(buffer, charBuffer, true); + // 切换为读取模式 + charBuffer.flip(); + + // 反向扫描换行符 + int endPos = charBuffer.length(); + for (int i = endPos - 1; i >= 0; i--) { + if (charBuffer.get(i) == '\n') { + linesFound++; + if (linesFound > maxLines || charsRead > maxChars) { + // 截取从换行符到结尾部分 + appendReversed(charBuffer, i + 1, endPos, result); + endPos = i; + break; + } + } + charsRead++; + } + if (linesFound <= maxLines && charsRead <= maxChars) { + appendReversed(charBuffer, 0, endPos, result); + } + } + } + return result.reverse(); + } + + private void appendReversed(CharBuffer src, int start, int end, StringBuilder dest) { + for (int i = end - 1; i >= start; i--) { + dest.append(src.get(i)); + } + } + +} diff --git a/src/main/java/neatlogic/module/tenant/api/log/GetLogFileNameListApi.java b/src/main/java/neatlogic/module/tenant/api/log/GetLogFileNameListApi.java new file mode 100644 index 00000000..84468833 --- /dev/null +++ b/src/main/java/neatlogic/module/tenant/api/log/GetLogFileNameListApi.java @@ -0,0 +1,162 @@ +/*Copyright (C) 2024 深圳极向量科技有限公司 All Rights Reserved. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see .*/ + +package neatlogic.module.tenant.api.log; + +import ch.qos.logback.classic.Level; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import neatlogic.framework.asynchronization.threadlocal.RequestContext; +import neatlogic.framework.auth.core.AuthAction; +import neatlogic.framework.auth.label.ADMIN; +import neatlogic.framework.common.config.Config; +import neatlogic.framework.common.constvalue.ApiParamType; +import neatlogic.framework.constvalue.SystemProperty; +import neatlogic.framework.exception.SystemPropertyNotFoundException; +import neatlogic.framework.exception.core.ApiRuntimeException; +import neatlogic.framework.exception.file.FileNotFoundException; +import neatlogic.framework.exception.server.ServerHostIsBankException; +import neatlogic.framework.exception.server.ServerNotFoundException; +import neatlogic.framework.heartbeat.dao.mapper.ServerMapper; +import neatlogic.framework.heartbeat.dto.ServerClusterVo; +import neatlogic.framework.integration.authentication.enums.AuthenticateType; +import neatlogic.framework.restful.annotation.*; +import neatlogic.framework.restful.constvalue.OperationTypeEnum; +import neatlogic.framework.restful.core.privateapi.PrivateApiComponentBase; +import neatlogic.framework.util.HttpRequestUtil; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.util.*; + +@AuthAction(action = ADMIN.class) +@Service +@OperationType(type = OperationTypeEnum.SEARCH) +public class GetLogFileNameListApi extends PrivateApiComponentBase { + private Logger logger = LoggerFactory.getLogger(GetLogFileNameListApi.class); + + @Resource + private ServerMapper serverMapper; + + @Override + public String getName() { + return "nmtal.getlogfilenamelistapi.getname"; + } + + @Input({ + @Param(name = "serverId", type = ApiParamType.INTEGER, isRequired = true, desc = "term.framework.serverid") + }) + @Output({ + @Param(name = "tbodyList", type = ApiParamType.INTEGER, desc = "common.tbodylist") + }) + @Description(desc = "nmtal.getlogfilenamelistapi.getname") + @Override + public Object myDoService(JSONObject paramObj) throws Exception { + JSONObject resultObj = new JSONObject(); + Integer serverId = paramObj.getInteger("serverId"); + if (Objects.equals(serverId, Config.SCHEDULE_SERVER_ID)) { + resultObj.put("level", getLoggerLevel(logger).levelStr); + String log4jHome = System.getProperties().getProperty(SystemProperty.LOG4J_HOME); + if (log4jHome != null) { + JSONArray tbodyList = new JSONArray(); + File dir = new File(log4jHome); + if (dir.exists()) { + File[] listFiles = dir.listFiles(); + if (listFiles != null) { + Arrays.sort(listFiles, Comparator.comparing(File::getName)); + for (File file : listFiles) { + if (file.isFile()) { + String fileName = file.getName(); + if (fileName.startsWith("neatloigc.") && fileName.endsWith(".acc")) { + continue; + } + JSONObject jsonObj = new JSONObject(); + jsonObj.put("fileName", fileName); + jsonObj.put("fileSize", FileUtils.byteCountToDisplaySize(file.length())); + tbodyList.add(jsonObj); + } + } + } + } else { + throw new FileNotFoundException(FileNotFoundException.Type.NONEXISTENT, log4jHome); + } + resultObj.put("tbodyList", tbodyList); + return resultObj; + } else { + throw new SystemPropertyNotFoundException(SystemProperty.LOG4J_HOME); + } + } else { + ServerClusterVo serverClusterVo = serverMapper.getServerByServerId(serverId); + if (serverClusterVo != null) { + String host = serverClusterVo.getHost(); + if (StringUtils.isNotBlank(host)) { + HttpServletRequest request = RequestContext.get().getRequest(); + String url = host + request.getRequestURI(); + HttpRequestUtil httpRequestUtil = HttpRequestUtil.post(url) + .setPayload(paramObj.toJSONString()) + .setAuthType(AuthenticateType.BUILDIN) + .setConnectTimeout(5000) + .setReadTimeout(5000) + .sendRequest(); + String error = httpRequestUtil.getError(); + if (StringUtils.isNotBlank(error)) { + throw new ApiRuntimeException(error); + } + JSONObject resultJson = httpRequestUtil.getResultJson(); + if (MapUtils.isNotEmpty(resultJson)) { + String status = resultJson.getString("Status"); + if (!"OK".equals(status)) { + throw new RuntimeException(resultJson.getString("Message")); + } + resultObj = resultJson.getJSONObject("Return"); + } + } else { + throw new ServerHostIsBankException(serverId); + } + } else { + throw new ServerNotFoundException(serverId); + } + return resultObj; + } + } + + @Override + public String getToken() { + return "log/filename/list"; + } + + private Level getLoggerLevel(Logger logger) { + if (logger.isTraceEnabled()) { + return Level.TRACE; + } else if (logger.isDebugEnabled()) { + return Level.DEBUG; + } else if (logger.isInfoEnabled()) { + return Level.INFO; + } else if (logger.isWarnEnabled()) { + return Level.WARN; + } else if (logger.isErrorEnabled()) { + return Level.ERROR; + } else { + return Level.OFF; + } + } +} diff --git a/src/main/java/neatlogic/module/tenant/api/server/GetServerListApi.java b/src/main/java/neatlogic/module/tenant/api/server/GetServerListApi.java index 8a012a10..0c203507 100644 --- a/src/main/java/neatlogic/module/tenant/api/server/GetServerListApi.java +++ b/src/main/java/neatlogic/module/tenant/api/server/GetServerListApi.java @@ -18,6 +18,8 @@ package neatlogic.module.tenant.api.server; import com.alibaba.fastjson.JSONObject; import neatlogic.framework.auth.core.AuthAction; import neatlogic.framework.auth.label.ADMIN; +import neatlogic.framework.common.config.Config; +import neatlogic.framework.common.constvalue.ApiParamType; import neatlogic.framework.heartbeat.dao.mapper.ServerMapper; import neatlogic.framework.heartbeat.dto.ServerClusterVo; import neatlogic.framework.heartbeat.dto.ServerCounterVo; @@ -25,10 +27,12 @@ import neatlogic.framework.restful.annotation.*; import neatlogic.framework.restful.constvalue.OperationTypeEnum; import neatlogic.framework.restful.core.privateapi.PrivateApiComponentBase; import neatlogic.framework.util.TableResultUtil; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; +import java.util.Objects; @AuthAction(action = ADMIN.class) @Service @@ -43,15 +47,28 @@ public class GetServerListApi extends PrivateApiComponentBase { return "nmtas.getserverlistapi.getname"; } - @Input({}) + @Input({ + @Param(name = "status", type = ApiParamType.ENUM, rule = "startup,stop", desc = "common.status") + }) @Output({ @Param(name = "tbodyList", explode = ServerCounterVo[].class, desc = "common.tbodylist") }) @Description(desc = "nmtas.getserverlistapi.getname") @Override public Object myDoService(JSONObject paramObj) throws Exception { + String status = paramObj.getString("status"); List list = serverMapper.getAllServerList(); - return TableResultUtil.getResult(list); + if (StringUtils.isNotBlank(status)) { + for (int i = list.size() - 1; i >= 0; i--) { + ServerClusterVo serverClusterVo = list.get(i); + if (!Objects.equals(serverClusterVo.getStatus(), status)) { + list.remove(i); + } + } + } + JSONObject resultObj = TableResultUtil.getResult(list); + resultObj.put("currentServerId", Config.SCHEDULE_SERVER_ID); + return resultObj; } @Override -- Gitee