diff --git a/CHANGELOG.md b/CHANGELOG.md
index 924de3ff8..8fbc6bc1e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@
(感谢 [@LeonChen21](https://gitee.com/leonchen21) [Gitee issues I67C3C](https://gitee.com/dromara/Jpom/issues/I67C3C) )
7. 【server】优化 websocket 控制台操作日志记录
8. 【server】修复 超级管理的 websocket 操作日志记录工作空间不正确
+9. 【agent】优化 插件端删除 spring-boot-starter-websocket 依赖
### ❌ 不兼容功能
diff --git a/modules/agent-transport/agent-transport-http/pom.xml b/modules/agent-transport/agent-transport-http/pom.xml
index 7bb728907..0e6cbf2fe 100644
--- a/modules/agent-transport/agent-transport-http/pom.xml
+++ b/modules/agent-transport/agent-transport-http/pom.xml
@@ -60,12 +60,17 @@
true
-
com.alibaba.fastjson2
fastjson2
true
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+ true
+
diff --git a/modules/agent/src/main/java/io/jpom/socket/AgentFileTailWatcher.java b/modules/agent/src/main/java/io/jpom/socket/AgentFileTailWatcher.java
index 65da9fc9a..bec0ce45e 100644
--- a/modules/agent/src/main/java/io/jpom/socket/AgentFileTailWatcher.java
+++ b/modules/agent/src/main/java/io/jpom/socket/AgentFileTailWatcher.java
@@ -24,6 +24,7 @@ package io.jpom.socket;
import cn.hutool.core.io.FileUtil;
import io.jpom.util.BaseFileTailWatcher;
+import io.jpom.util.SocketSessionUtil;
import lombok.extern.slf4j.Slf4j;
import javax.websocket.Session;
@@ -151,6 +152,14 @@ public class AgentFileTailWatcher extends BaseFileTailWatcher {
}
+ @Override
+ protected void send(T session, String msg) {
+ try {
+ SocketSessionUtil.send((Session) session, msg);
+ } catch (Exception e) {
+ log.error("发送消息异常", e);
+ }
+ }
/**
* 关闭
diff --git a/modules/agent/src/main/java/io/jpom/socket/AgentWebSocketConfig.java b/modules/agent/src/main/java/io/jpom/socket/AgentWebSocketConfig.java
index 32e5109d8..517906cdc 100644
--- a/modules/agent/src/main/java/io/jpom/socket/AgentWebSocketConfig.java
+++ b/modules/agent/src/main/java/io/jpom/socket/AgentWebSocketConfig.java
@@ -22,9 +22,21 @@
*/
package io.jpom.socket;
-import org.springframework.context.annotation.Bean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.SmartInitializingSingleton;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
-import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+import org.springframework.util.Assert;
+import org.springframework.web.context.support.WebApplicationObjectSupport;
+
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
+import javax.websocket.server.ServerEndpoint;
+import javax.websocket.server.ServerEndpointConfig;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
/**
* 插件端socket 配置
@@ -33,10 +45,91 @@ import org.springframework.web.socket.server.standard.ServerEndpointExporter;
* @since 2019/4/19
*/
@Configuration
-public class AgentWebSocketConfig {
+public class AgentWebSocketConfig extends WebApplicationObjectSupport implements InitializingBean, SmartInitializingSingleton {
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ //Assert.state(this.serverContainer != null, "javax.websocket.server.ServerContainer not available");
+ }
+
+
+// @Override
+// protected void initServletContext(ServletContext servletContext) {
+// if (this.serverContainer == null) {
+// this.serverContainer = (ServerContainer) servletContext.getAttribute("javax.websocket.server.ServerContainer");
+// }
+// }
+
+ private ServerContainer getServerContainer() {
+ return (ServerContainer) Objects.requireNonNull(getServletContext()).getAttribute("javax.websocket.server.ServerContainer");
+ }
+
+ @Override
+ protected boolean isContextRequired() {
+ return true;
+ }
+
+ @Override
+ public void afterSingletonsInstantiated() {
+ registerEndpoints();
+ }
+
+ protected void registerEndpoints() {
+ Set> endpointClasses = new LinkedHashSet<>();
+
+ ApplicationContext context = getApplicationContext();
+ if (context != null) {
+ String[] endpointBeanNames = context.getBeanNamesForAnnotation(ServerEndpoint.class);
+ for (String beanName : endpointBeanNames) {
+ endpointClasses.add(context.getType(beanName));
+ }
+ }
+
+ for (Class> endpointClass : endpointClasses) {
+ registerEndpoint(endpointClass);
+ }
+
+ if (context != null) {
+ Map endpointConfigMap = context.getBeansOfType(ServerEndpointConfig.class);
+ for (ServerEndpointConfig endpointConfig : endpointConfigMap.values()) {
+ registerEndpoint(endpointConfig);
+ }
+ }
+ }
+
+ private void registerEndpoint(Class> endpointClass) {
+ ServerContainer serverContainer = getServerContainer();
+ Assert.state(serverContainer != null,
+ "No ServerContainer set. Most likely the server's own WebSocket ServletContainerInitializer " +
+ "has not run yet. Was the Spring ApplicationContext refreshed through a " +
+ "org.springframework.web.context.ContextLoaderListener, " +
+ "i.e. after the ServletContext has been fully initialized?");
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Registering @ServerEndpoint class: " + endpointClass);
+ }
+ serverContainer.addEndpoint(endpointClass);
+ } catch (DeploymentException ex) {
+ throw new IllegalStateException("Failed to register @ServerEndpoint class: " + endpointClass, ex);
+ }
+ }
+
+ private void registerEndpoint(ServerEndpointConfig endpointConfig) {
+ ServerContainer serverContainer = this.getServerContainer();
+ Assert.state(serverContainer != null, "No ServerContainer set");
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Registering ServerEndpointConfig: " + endpointConfig);
+ }
+ serverContainer.addEndpoint(endpointConfig);
+ } catch (DeploymentException ex) {
+ throw new IllegalStateException("Failed to register ServerEndpointConfig: " + endpointConfig, ex);
+ }
+ }
+
+// @Bean
+// public ServerEndpointExporter serverEndpointExporter() {
+// return new ServerEndpointExporter();
+// }
}
diff --git a/modules/agent/src/main/java/io/jpom/util/SocketSessionUtil.java b/modules/agent/src/main/java/io/jpom/util/SocketSessionUtil.java
new file mode 100644
index 000000000..9c7c9ef62
--- /dev/null
+++ b/modules/agent/src/main/java/io/jpom/util/SocketSessionUtil.java
@@ -0,0 +1,89 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package io.jpom.util;
+
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.websocket.Session;
+import java.io.IOException;
+
+/**
+ * socket 会话对象
+ *
+ * @author jiangzeyin
+ * @since 2018/9/29
+ */
+@Slf4j
+public class SocketSessionUtil {
+ /**
+ * 锁
+ */
+ private static final KeyLock LOCK = new KeyLock<>();
+ /**
+ * 错误尝试次数
+ */
+ private static final int ERROR_TRY_COUNT = 10;
+
+ /**
+ * 发送消息
+ *
+ * @param session 会话对象
+ * @param msg 消息
+ * @throws IOException 异常
+ */
+ public static void send(final Session session, String msg) throws IOException {
+ if (StrUtil.isEmpty(msg)) {
+ return;
+ }
+ if (!session.isOpen()) {
+ throw new RuntimeException("session close ");
+ }
+ try {
+ LOCK.lock(session.getId());
+ IOException exception = null;
+ int tryCount = 0;
+ do {
+ tryCount++;
+ if (exception != null) {
+ // 上一次有异常、休眠 500
+ ThreadUtil.sleep(500);
+ }
+ try {
+ session.getBasicRemote().sendText(msg);
+ exception = null;
+ break;
+ } catch (IOException e) {
+ log.error("发送消息失败:" + tryCount, e);
+ exception = e;
+ }
+ } while (tryCount <= ERROR_TRY_COUNT);
+ if (exception != null) {
+ throw exception;
+ }
+ } finally {
+ LOCK.unlock(session.getId());
+ }
+ }
+}
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index 916d88076..f5e71158b 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -82,10 +82,7 @@
cn.hutool
hutool-cache
-
- org.springframework.boot
- spring-boot-starter-websocket
-
+
org.springframework.boot
diff --git a/modules/common/src/main/java/io/jpom/common/ILoadEvent.java b/modules/common/src/main/java/io/jpom/common/ILoadEvent.java
index cc38093c2..e3f5fda4e 100644
--- a/modules/common/src/main/java/io/jpom/common/ILoadEvent.java
+++ b/modules/common/src/main/java/io/jpom/common/ILoadEvent.java
@@ -1,3 +1,25 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
package io.jpom.common;
import org.springframework.context.ApplicationContext;
diff --git a/modules/common/src/main/java/io/jpom/util/BaseFileTailWatcher.java b/modules/common/src/main/java/io/jpom/util/BaseFileTailWatcher.java
index 57e91c427..38479cabb 100644
--- a/modules/common/src/main/java/io/jpom/util/BaseFileTailWatcher.java
+++ b/modules/common/src/main/java/io/jpom/util/BaseFileTailWatcher.java
@@ -26,14 +26,10 @@ import cn.hutool.core.date.DateUnit;
import cn.hutool.core.io.file.Tailer;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
-import io.jpom.system.JpomRuntimeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
-import org.springframework.web.socket.WebSocketSession;
-import javax.websocket.Session;
import java.io.File;
-import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.HashSet;
@@ -73,18 +69,19 @@ public abstract class BaseFileTailWatcher {
this.charset = charset;
}
- protected void send(T session, String msg) {
- try {
- if (session instanceof Session) {
- SocketSessionUtil.send((Session) session, msg);
- } else if (session instanceof WebSocketSession) {
- SocketSessionUtil.send((WebSocketSession) session, msg);
- } else {
- throw new JpomRuntimeException("没有对应类型");
- }
- } catch (IOException ignored) {
- }
- }
+ protected abstract void send(T session, String msg);
+ //{
+// try {
+// if (session instanceof Session) {
+// SocketSessionUtil.send((Session) session, msg);
+// } else if (session instanceof WebSocketSession) {
+// SocketSessionUtil.send((WebSocketSession) session, msg);
+// } else {
+// throw new JpomRuntimeException("没有对应类型");
+// }
+// } catch (IOException ignored) {
+// }
+ //}
/**
* 有新的日志
diff --git a/modules/common/src/main/java/io/jpom/util/SocketSessionUtil.java b/modules/common/src/main/java/io/jpom/util/SocketSessionUtil.java
deleted file mode 100644
index a0a90397e..000000000
--- a/modules/common/src/main/java/io/jpom/util/SocketSessionUtil.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Code Technology Studio
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-package io.jpom.util;
-
-import cn.hutool.core.thread.ThreadUtil;
-import cn.hutool.core.util.StrUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.socket.TextMessage;
-import org.springframework.web.socket.WebSocketSession;
-
-import javax.websocket.Session;
-import java.io.IOException;
-
-/**
- * socket 会话对象
- *
- * @author jiangzeyin
- * @since 2018/9/29
- */
-@Slf4j
-public class SocketSessionUtil {
- /**
- * 锁
- */
- private static final KeyLock LOCK = new KeyLock<>();
- /**
- * 错误尝试次数
- */
- private static final int ERROR_TRY_COUNT = 10;
-
- /**
- * 发送消息
- *
- * @param session 会话对象
- * @param msg 消息
- * @throws IOException 异常
- */
- public static void send(final Session session, String msg) throws IOException {
- if (StrUtil.isEmpty(msg)) {
- return;
- }
- if (!session.isOpen()) {
- throw new RuntimeException("session close ");
- }
- try {
- LOCK.lock(session.getId());
- IOException exception = null;
- int tryCount = 0;
- do {
- tryCount++;
- if (exception != null) {
- // 上一次有异常、休眠 500
- ThreadUtil.sleep(500);
- }
- try {
- session.getBasicRemote().sendText(msg);
- exception = null;
- break;
- } catch (IOException e) {
- log.error("发送消息失败:" + tryCount, e);
- exception = e;
- }
- } while (tryCount <= ERROR_TRY_COUNT);
- if (exception != null) {
- throw exception;
- }
- } finally {
- LOCK.unlock(session.getId());
- }
- }
-
- public static void send(WebSocketSession session, String msg) throws IOException {
- if (StrUtil.isEmpty(msg)) {
- return;
- }
- if (!session.isOpen()) {
- throw new RuntimeException("session close ");
- }
- try {
- LOCK.lock(session.getId());
- IOException exception = null;
- int tryCount = 0;
- do {
- tryCount++;
- if (exception != null) {
- // 上一次有异常、休眠 500
- ThreadUtil.sleep(500);
- }
- try {
- session.sendMessage(new TextMessage(msg));
- exception = null;
- break;
- } catch (IOException e) {
- log.error("发送消息失败:" + tryCount, e);
- exception = e;
- }
- } while (tryCount <= ERROR_TRY_COUNT);
- if (exception != null) {
- throw exception;
- }
- } finally {
- LOCK.unlock(session.getId());
- }
- }
-}
diff --git a/modules/server/pom.xml b/modules/server/pom.xml
index 575fd9638..5c091ac1e 100644
--- a/modules/server/pom.xml
+++ b/modules/server/pom.xml
@@ -126,6 +126,11 @@
agent-transport-http
${project.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
diff --git a/modules/server/src/main/java/io/jpom/socket/ServiceFileTailWatcher.java b/modules/server/src/main/java/io/jpom/socket/ServiceFileTailWatcher.java
index cec1fe8d6..d0e105d11 100644
--- a/modules/server/src/main/java/io/jpom/socket/ServiceFileTailWatcher.java
+++ b/modules/server/src/main/java/io/jpom/socket/ServiceFileTailWatcher.java
@@ -24,6 +24,7 @@ package io.jpom.socket;
import cn.hutool.core.io.FileUtil;
import io.jpom.util.BaseFileTailWatcher;
+import io.jpom.util.SocketSessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.WebSocketSession;
@@ -140,6 +141,15 @@ public class ServiceFileTailWatcher extends BaseFileTailWatcher {
}
}
+ @Override
+ protected void send(T session, String msg) {
+ try {
+ SocketSessionUtil.send((WebSocketSession) session, msg);
+ } catch (Exception e) {
+ log.error("发送消息异常", e);
+ }
+ }
+
/**
* 关闭
*/
diff --git a/modules/server/src/main/java/io/jpom/util/SocketSessionUtil.java b/modules/server/src/main/java/io/jpom/util/SocketSessionUtil.java
new file mode 100644
index 000000000..1abc7a770
--- /dev/null
+++ b/modules/server/src/main/java/io/jpom/util/SocketSessionUtil.java
@@ -0,0 +1,83 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package io.jpom.util;
+
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+
+import java.io.IOException;
+
+/**
+ * socket 会话对象
+ *
+ * @author jiangzeyin
+ * @since 2018/9/29
+ */
+@Slf4j
+public class SocketSessionUtil {
+ /**
+ * 锁
+ */
+ private static final KeyLock LOCK = new KeyLock<>();
+ /**
+ * 错误尝试次数
+ */
+ private static final int ERROR_TRY_COUNT = 10;
+
+ public static void send(WebSocketSession session, String msg) throws IOException {
+ if (StrUtil.isEmpty(msg)) {
+ return;
+ }
+ if (!session.isOpen()) {
+ throw new RuntimeException("session close ");
+ }
+ try {
+ LOCK.lock(session.getId());
+ IOException exception = null;
+ int tryCount = 0;
+ do {
+ tryCount++;
+ if (exception != null) {
+ // 上一次有异常、休眠 500
+ ThreadUtil.sleep(500);
+ }
+ try {
+ session.sendMessage(new TextMessage(msg));
+ exception = null;
+ break;
+ } catch (IOException e) {
+ log.error("发送消息失败:" + tryCount, e);
+ exception = e;
+ }
+ } while (tryCount <= ERROR_TRY_COUNT);
+ if (exception != null) {
+ throw exception;
+ }
+ } finally {
+ LOCK.unlock(session.getId());
+ }
+ }
+}