目录
一. 写本文的初衷
二. 实例概述
三. 开始实践
1. 引入依赖
2. Websocket 相关配置
3. 创建消息数量单例
4. 创建操作枚举
5. 主要服务类
<1> sendMessage
<2> broadcast
6. 消息数量单例控制器
7. 前端页面
<1>页面结构
<2>js部分
8. 效果展示
一. 写本文的初衷
学习如何使用 WebSocket 技术,了解Java全双端通信。通过实践下面这个实例,以便于更好的理解。(最后附上了本demo的gitee地址,有需要可以随时下载)
二. 实例概述
使用单例模式+WebSocket向前端用户提示需要处理的消息数量。这里的单例模式用来存储消息的数量,将初始数量设置为10。这里的"+"号和"-"是一个抽象的概念,泛指用户在某数据上做的操作使得该数据增加或减少。
三. 开始实践
1. 引入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.2</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependencies>
2. Websocket 相关配置
@Configurationpublic class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }}
3. 创建消息数量单例
由于此单例需要频繁使用,所以创建为饿汉式单例。public class CountSingle { private Integer count = 10; private final static CountSingle countSingle = new CountSingle(); public static Integer getCount() { return getInstance().count; } public static synchronized void setCount(OperEnum operEnum) { if (operEnum == OperEnum.ADD) { getInstance().count++; } if (operEnum == OperEnum.SUB) { getInstance().count--; } } public static CountSingle getInstance() { return countSingle; }}
4. 创建操作枚举
此枚举分别对应用户做的加或减操作
public enum OperEnum { ADD(1), SUB(2); private final Integer code; OperEnum(int code) { this.code = code; } public Integer getCode() { return code; }}
5. 主要服务类
这里主要说两个重要的方法:
<1> sendMessage
向当前会话主体对象发送信息
<2> broadcast
向所有会话主体对象广播信息
@Component@ServerEndpoint("/websocket")public class WebSocketServer { private static final CopyOnWriteArraySet<WebSocketServer> connections = new CopyOnWriteArraySet<>(); private Session session; @OnOpen public void onOpen(Session session) { this.session = session; connections.add(this); this.sendMessage(String.valueOf(CountSingle.getCount())); System.out.println("新建连接: " + session.getId()); } @OnClose public void onClose() { connections.remove(this); System.out.println("连接关闭: " + session.getId()); } @OnError public void onError(Throwable error) { error.printStackTrace(); } private void sendMessage(String message) { try { this.session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } public static void broadcast(String message) { for (WebSocketServer client : connections) { client.sendMessage(message); } }}
6. 消息数量单例控制器
@RestControllerpublic class CountController { @GetMapping("add") public void add() { CountSingle.setCount(OperEnum.ADD); WebSocketServer.broadcast(String.valueOf(CountSingle.getCount())); } @GetMapping("sub") public void sub() { CountSingle.setCount(OperEnum.SUB); WebSocketServer.broadcast(String.valueOf(CountSingle.getCount())); }}
7. 前端页面
<1>页面结构
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="/lib/jquery-3.4.1.min.js"></script> <script src="/lib/layui-v2.5.5/layui.js"></script> <link rel="stylesheet" href="/lib/layui-v2.5.5/css/layui.css"> <style> div { text-align: center; } </style></head><body><div> <button class="layui-btn layui-btn-sm layui-btn-normal" onclick="add()">+</button> <button class="layui-btn layui-btn-sm layui-btn-warm" onclick="sub()">-</button> <button class="layui-btn">查看消息<span class="layui-badge layui-bg-gray" id="count"></span></button></div>
<2>js部分
let socket = new WebSocket("ws://localhost:8080/websocket"); socket.onmessage = function (event) { $("#count").text(event.data); }; function add() { $.ajax({ url: '/add', // 请求的 URL type: 'GET', // 请求方法:GET、POST 等 dataType: 'json', // 预期服务器返回的数据类型 }); } function sub() { $.ajax({ url: '/sub', // 请求的 URL type: 'GET', // 请求方法:GET、POST 等 dataType: 'json', // 预期服务器返回的数据类型 }); }
8. 效果展示
这里需要使用两个浏览器才能看到效果。
websocket测试
项目gitee地址:WebsocketTest: 本系统做一个简单的应用,使用单例模式+WebSocket向前端提示需要处理的消息数量。