From e6fc12cde84fb1a4c18d89966f6ddd5d2b11be49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E8=8B=B1=E6=9D=B0?= <327782001@qq.com> Date: Sat, 26 Aug 2023 17:01:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=B7=BB=E5=8A=A0websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 ++ .../kwan/springbootkwan/aop/LogAspect.java | 4 +- .../config/WebSocketConfig.java | 21 +++ .../controller/SystemController.java | 40 ++++++ .../service/WebSocketServer.java | 133 ++++++++++++++++++ src/main/resources/application-local.yml | 6 +- src/main/resources/index.html | 74 ++++++++++ .../utils/StringEncryptorUtil.java | 41 ++++++ 8 files changed, 327 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/kwan/springbootkwan/config/WebSocketConfig.java create mode 100644 src/main/java/com/kwan/springbootkwan/controller/SystemController.java create mode 100644 src/main/java/com/kwan/springbootkwan/service/WebSocketServer.java create mode 100644 src/main/resources/index.html create mode 100644 src/test/java/com/kwan/springbootkwan/utils/StringEncryptorUtil.java diff --git a/pom.xml b/pom.xml index 1c38cf5..3728a99 100644 --- a/pom.xml +++ b/pom.xml @@ -211,6 +211,16 @@ springfox-swagger-ui ${swagger.version} + + com.github.ulisesbocchio + jasypt-spring-boot-starter + 2.1.0 + + + org.springframework.boot + spring-boot-starter-websocket + 2.6.6 + diff --git a/src/main/java/com/kwan/springbootkwan/aop/LogAspect.java b/src/main/java/com/kwan/springbootkwan/aop/LogAspect.java index 0eded31..3a52a3c 100644 --- a/src/main/java/com/kwan/springbootkwan/aop/LogAspect.java +++ b/src/main/java/com/kwan/springbootkwan/aop/LogAspect.java @@ -17,7 +17,9 @@ import org.springframework.stereotype.Component; @Aspect @Slf4j public class LogAspect { - @Pointcut(value = "execution(* com.kwan.springbootkwan.service.*.*(..))") + + @Pointcut(value = "execution(* com.kwan.springbootkwan.service.*.*(..)) && !execution(* com.kwan.springbootkwan.service.WebSocketServer.*(..))") + public void pcl() { } diff --git a/src/main/java/com/kwan/springbootkwan/config/WebSocketConfig.java b/src/main/java/com/kwan/springbootkwan/config/WebSocketConfig.java new file mode 100644 index 0000000..ee016f6 --- /dev/null +++ b/src/main/java/com/kwan/springbootkwan/config/WebSocketConfig.java @@ -0,0 +1,21 @@ +package com.kwan.springbootkwan.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + + +/** + * 开启websocket的支持 + * + * @author : qinyingjie + * @version : 2.2.0 + * @date : 2023/8/26 16:45 + */ +@Configuration +public class WebSocketConfig { + @Bean + public ServerEndpointExporter serverEndpointExporter() { + return new ServerEndpointExporter(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kwan/springbootkwan/controller/SystemController.java b/src/main/java/com/kwan/springbootkwan/controller/SystemController.java new file mode 100644 index 0000000..1950674 --- /dev/null +++ b/src/main/java/com/kwan/springbootkwan/controller/SystemController.java @@ -0,0 +1,40 @@ +package com.kwan.springbootkwan.controller; + +import com.kwan.springbootkwan.service.WebSocketServer; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +@Controller("web_Scoket_system") +@RequestMapping("/api/socket") +public class SystemController { + //页面请求 + @GetMapping("/index/{userId}") + public ModelAndView socket(@PathVariable String userId) { + ModelAndView mav = new ModelAndView("/socket1"); + mav.addObject("userId", userId); + return mav; + } + + //推送数据接口 + @ResponseBody + @RequestMapping("/socket/push/{cid}") + public Map pushToWeb(@PathVariable String cid, String message) { + Map result = new HashMap<>(); + try { + WebSocketServer.sendInfo(message, cid); + result.put("code", cid); + result.put("msg", message); + } catch (IOException e) { + e.printStackTrace(); + } + return result; + } +} diff --git a/src/main/java/com/kwan/springbootkwan/service/WebSocketServer.java b/src/main/java/com/kwan/springbootkwan/service/WebSocketServer.java new file mode 100644 index 0000000..fe84608 --- /dev/null +++ b/src/main/java/com/kwan/springbootkwan/service/WebSocketServer.java @@ -0,0 +1,133 @@ +package com.kwan.springbootkwan.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; +import java.io.IOException; +import java.util.concurrent.CopyOnWriteArraySet; + +@Component +@Slf4j +@ServerEndpoint(value = "/api/websocket/{sid}") +public class WebSocketServer { + + //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 + private static int onlineCount = 0; + //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 + private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>(); + + //与某个客户端的连接会话,需要通过它来给客户端发送数据 + private Session session; + + //接收sid + private String sid = ""; + + /** + * 连接建立成功调用的方法 + */ + @OnOpen + public void onOpen(Session session, @PathParam("sid") String sid) { + this.session = session; + webSocketSet.add(this); //加入set中 + this.sid = sid; + addOnlineCount(); //在线数加1 + try { + sendMessage("conn_success"); + log.info("有新窗口开始监听:" + sid + ",当前在线人数为:" + getOnlineCount()); + } catch (IOException e) { + log.error("websocket IO Exception"); + } + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose() { + webSocketSet.remove(this); //从set中删除 + subOnlineCount(); //在线数减1 + //断开连接情况下,更新主板占用情况为释放 + log.info("释放的sid为:" + sid); + //这里写你 释放的时候,要处理的业务 + log.info("有一连接关闭!当前在线人数为" + getOnlineCount()); + + } + + /** + * 收到客户端消息后调用的方法 + * + * @ Param message 客户端发送过来的消息 + */ + @OnMessage + public void onMessage(String message, Session session) { + log.info("收到来自窗口" + sid + "的信息:" + message); + //群发消息 + for (WebSocketServer item : webSocketSet) { + try { + item.sendMessage(message); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * @ Param session + * @ Param error + */ + @OnError + public void onError(Session session, Throwable error) { + log.error("发生错误"); + error.printStackTrace(); + } + + /** + * 实现服务器主动推送 + */ + public void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + + /** + * 群发自定义消息 + */ + public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException { + log.info("推送消息到窗口" + sid + ",推送内容:" + message); + + for (WebSocketServer item : webSocketSet) { + try { + //这里可以设定只推送给这个sid的,为null则全部推送 + if (sid == null) { +// item.sendMessage(message); + } else if (item.sid.equals(sid)) { + item.sendMessage(message); + } + } catch (IOException e) { + continue; + } + } + } + + public static synchronized int getOnlineCount() { + return onlineCount; + } + + public static synchronized void addOnlineCount() { + WebSocketServer.onlineCount++; + } + + public static synchronized void subOnlineCount() { + WebSocketServer.onlineCount--; + } + + public static CopyOnWriteArraySet getWebSocketSet() { + return webSocketSet; + } +} diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 2a5fad0..eb3f74e 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -41,4 +41,8 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://120.79.36.53:3306/kwan?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root - password: 15671628341Qwe. \ No newline at end of file + password: 15671628341Qwe. +# jasypt加密的密匙 +jasypt: + encryptor: + password: Y6M9fAJQdU7jNp5MW \ No newline at end of file diff --git a/src/main/resources/index.html b/src/main/resources/index.html new file mode 100644 index 0000000..20f4396 --- /dev/null +++ b/src/main/resources/index.html @@ -0,0 +1,74 @@ + + + + + + Java后端WebSocket的Tomcat实现 + + + + +
+Welcome
+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/src/test/java/com/kwan/springbootkwan/utils/StringEncryptorUtil.java b/src/test/java/com/kwan/springbootkwan/utils/StringEncryptorUtil.java new file mode 100644 index 0000000..7535666 --- /dev/null +++ b/src/test/java/com/kwan/springbootkwan/utils/StringEncryptorUtil.java @@ -0,0 +1,41 @@ +package com.kwan.springbootkwan.utils; + +import com.kwan.springbootkwan.SpringBootKwanApplication; +import org.jasypt.encryption.StringEncryptor; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + + +/** + * 加解密工具测试 + * + * @author : qinyingjie + * @version : 2.2.0 + * @date : 2023/8/26 15:49 + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@ContextConfiguration(classes = SpringBootKwanApplication.class) +public class StringEncryptorUtil { + + @Autowired + private StringEncryptor encryptor; + + @Test + public void getPass() { + String url = encryptor.encrypt("jdbc:mysql://localhost:3306/mydb?autoReconnect=true&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8"); + String name = encryptor.encrypt("root"); + String password = encryptor.encrypt("123456"); + System.out.println("database url: " + url); + System.out.println("database name: " + name); + System.out.println("database password: " + password); + Assert.assertTrue(url.length() > 0); + Assert.assertTrue(name.length() > 0); + Assert.assertTrue(password.length() > 0); + } +} \ No newline at end of file -- GitLab