SpringBoot + webSocket + stomp +thymeleaf 推流
一、引入依赖
<!-- websocket推流--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
<!--thymeleaf模板--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
|
二、后端配置
1、新建一个 WebSocketStompConfig 类来实现 WebSocketMessageBrokerConfigurer
//交给SpringBoot管理 @Configuration //注解开启使用STOMP协议来传输基于代理(message broker)的消息 @EnableWebSocketMessageBroker @Order(1) public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
/** * 注册stomp的端点(endpoint),并映射指定的url */ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { /* 允许使用socketJs方式访问,访问点为webSocketServer,允许跨域 在网页上我们就可以通过这个链接 http://localhost:8080/webSocket/server 来和服务器的WebSocket连接*/
//注册一个STOMP的endpoint,并指定使用SockJS协议 registry.addEndpoint("/websocket/server").setAllowedOrigins("*").withSockJS(); }
/** * 配置信息代理 */ @Override public void configureMessageBroker(MessageBrokerRegistry registry) { // 订阅Broker名称 //两个域上可以向客户端发消息 registry.enableSimpleBroker("/queue", "/topic", "/user");
// 全局使用的消息前缀(客户端订阅路径上会体现出来) //客户端向服务端发送时的主题上面需要加"/app"作为前缀 // registry.setApplicationDestinationPrefixes("/app"); // 点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/ // registry.setUserDestinationPrefix("/user"); } |
三、后端向前端推流
1、创建Controller控制层
@Slf4j @Controller @Api(tags = "webSocket推流") public class WebSocketRest{
//依赖messageTemplate发送模板 @Autowired private SimpMessagingTemplate messagingTemplate ;
/* * 跳转webSocket测试页面 * */ @GetMapping("webPage") @ApiOperation(value = "webPage 页面跳转") public String webPage(){ log.info("forward:web"); return "webscoket"; } } |
2、创建service服务层 (订阅后)
@Service public class WebSocketService { @Resource private SimpMessagingTemplate messagingTemplate ;
/* * 每隔1s向 "/topic/hello" 中 推送信息 * */ @Scheduled(fixedDelay = 1000) public String sendTest01(){ messagingTemplate.convertAndSend("/topic/hello",new ServerMessage("hello webSocket !!! >>> hello ")) ; return "message" ; } } |
3、编写前端页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head> <meta charset="UTF-8" /> <title>Spring Boot+WebSocket+广播式(点对点)</title> </head> <body onload="disconnect()"> <noscript> <h2 style="color: #ff0000">貌似你的浏览器不支持websocket</h2> </noscript> <div> <div> <button id="hello" onclick="hello();">hello连接</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button> </div> </div> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/sockjs-client/1.5.0/sockjs.min.js}"></script> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/stomp.js/2.3.3/stomp.min.js}"></script> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js}"></script> <script type="text/javascript"> var stompClient = null; function hello() { //若前后端分离,url要写全,若在一个项目内,只写/websocket/server就行 var url = "http://ip:8080/websocket/server" var socket = new SockJS(url); //链接SockJS 的endpoint 名称为后台声明的"/websocket/server" stompClient = Stomp.over(socket);//使用stomp子协议的WebSocket 客户端 stompClient.connect({}, function(frame) {//链接Web Socket的服务端。 console.log('Connected: ' + frame); //广播式发送,订阅地址不需要加唯一标识;点对点发送,可自定义唯一标识 var subUrl= '/topic/hello'; stompClient.subscribe(subUrl, function(respnose){ //订阅/topic/getResponse 目标发送的消息。这个是在控制器的@SendTo中定义的。 showResponse(JSON.parse(respnose.body).name); }); }); }
//断开连接 function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } </script> </body> </html> |
4、效果
五、前端向后端推送消息
1、创建Controller控制层
@Slf4j @Controller @Api(tags = "webSocket推流") public class WebSocketRest{
//依赖messageTemplate发送模板 @Autowired private SimpMessagingTemplate messagingTemplate ;
/* * 跳转webSocket测试页面 * */ @GetMapping("webPage") @ApiOperation(value = "webPage 页面跳转") public String webPage(){ log.info("forward:web"); return "webscoket"; }
/* * 接收到 客户端的消息 * */ @ResponseBody @MessageMapping(value = "/welcome") public void userChat(Message message) throws Exception { String url = "/topic/getResponse/"+message.getName(); messagingTemplate.convertAndSend(url, "welcome!"); } } |
2、编写前端页面
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Spring Boot+WebSocket+广播式(点对点)</title>
</head> <body onload="disconnect()"> <noscript><h2 style="color: #ff0000">貌似你的浏览器不支持websocket</h2></noscript> <div> <div> <!-- <button id="connect" onclick="connect();">connect连接</button>--> <button id="hello" onclick="hello();">hello连接</button> <button id="serverReturnMessage" onclick="serverReturnMessage();">serverReturnMessage连接</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button>
</div> <div id="conversationDiv"> <label>输入你的信息</label><input type="text" id="name" /> <button id="sendName" onclick="sendName();">发送</button> <p id="response"></p> </div> </div> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/sockjs-client/1.5.0/sockjs.min.js}"></script> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/stomp.js/2.3.3/stomp.min.js}"></script> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js}"></script> <script type="text/javascript"> var stompClient = null;
function setConnected(flag) { // document.getElementById('connect').disabled = flag; document.getElementById('disconnect').disabled = !flag; document.getElementById('conversationDiv').style.visibility = flag ? 'visible' : 'hidden'; }
function serverReturnMessage() { //若前后端分离,url要写全,若在一个项目内,只写/websocket/server就行 var url = "http://ip:8080/websocket/server" var socket = new SockJS(url); //链接SockJS 的endpoint 名称为后台声明的"/websocket/server" stompClient = Stomp.over(socket);//使用stomp子协议的WebSocket 客户端 stompClient.connect({}, function(frame) {//链接Web Socket的服务端。 setConnected(true); console.log('Connected: ' + frame); //广播式发送,订阅地址不需要加唯一标识;点对点发送,可自定义唯一标识 var subUrl= '/topic/serverReturnMessage'; stompClient.subscribe(subUrl, function(respnose){ //订阅/topic/getResponse 目标发送的消息。这个是在控制器的@SendTo中定义的。 showResponse(JSON.parse(respnose.body).name); }); }); }
//断开连接 function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); }
function showResponse(message) { var response = $("#response"); console.log(message); } //向stompClient发送请求 function sendName() { var name = $('#name').val(); //通过stompClient.send 向/welcome 目标 发送消息,这个是在控制器的@messageMapping 中定义的。 //在这里,可根据业务自定义json,甚至可以把订阅地址的唯一标识在此传入给后台解析 var obj = JSON.stringify({'name': name, 'retailmId': '001'})
stompClient.send("/sendTest", {}, obj); } </script> </body> </html> |
3、效果
六、点对点推流
1、修改WebSocketStompConfig配置文件。将标记行注释取消。
2、创建服务层
@Service public class WebSocketService { @Resource private SimpMessagingTemplate messagingTemplate ;
/* *点对点消息推送 * */ @Scheduled(fixedDelay = 1000) public void userChat() throws Exception { String url = "/user/nodeSendNode/"; String username = "zhangsan"; messagingTemplate.convertAndSendToUser(username, url ," 点 对 点 推送!"); } } |
3、编写前端页面
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Spring Boot+WebSocket+广播式(点对点)</title>
</head> <body onload="disconnect()"> <noscript><h2 style="color: #ff0000">貌似你的浏览器不支持websocket</h2></noscript> <div> <div> <button id="nodeSendNode" onclick="nodeSendNode();">nodeSendNode连接</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button> </div> </div> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/sockjs-client/1.5.0/sockjs.min.js}"></script> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/stomp.js/2.3.3/stomp.min.js}"></script> <script th:src="@{https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js}"></script> <!--<script th:src="@{sockjs.js}"></script> <script th:src="@{stomp.js}"></script> <script th:src="@{jquery.js}"></script>--> <script type="text/javascript"> var stompClient = null;
function setConnected(flag) { // document.getElementById('connect').disabled = flag; document.getElementById('disconnect').disabled = !flag; document.getElementById('conversationDiv').style.visibility = flag ? 'visible' : 'hidden'; }
//点对点 function nodeSendNode() { //配置用户名 用于接收但对点消息 var username = 'zhangsan'; //若前后端分离,url要写全,若在一个项目内,只写/websocket/server就行 var url = "http://10.20.37.64:8080/websocket/server" var socket = new SockJS(url); //链接SockJS 的endpoint 名称为后台声明的"/websocket/server" stompClient = Stomp.over(socket);//使用stomp子协议的WebSocket 客户端 stompClient.connect({}, function(frame) {//链接Web Socket的服务端。 setConnected(true); console.log('Connected: ' + frame); //点对点发送,订阅地址不需要加唯一标识;点对点发送,可自定义唯一标识 var subUrl= '/user/nodeSendNode/'; //订阅/topic/getResponse 目标发送的消息。这个是在控制器的@SendTo中定义的。 stompClient.subscribe('/user/'+ username +subUrl, function(respnose){ console.log(respnose.body); }); }); }
//断开连接 function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); }
function showResponse(message) { var response = $("#response"); console.log(message); } </script> </body> </html> |
4、效果