19_SpringBoot WebSocket 广播式
- WebSocket 是为浏览器和服务端提供双工异步通信的功能
- 浏览器可以向服务端发送消息,服务端也可以向浏览器发送消息
- WebSocket 需要浏览器的支持(现在的浏览器基本上都支持)
- WebSocket 通过一个 socket 来实现双工异步通信能力
- 直接使用 WebSocket 开发比较繁琐,可以直接使用它的子协议 STOMP 它是一个更高级别的协议
- STOMP 使用一个基于桢的格式来定义消息,与 HTTP 的 request response 类似
1,SpringBoot 通过的自动配置
- 创建项目,选择
WebSocket
Thymeleaf
两个依赖 - 什么是广播式:当服务端有消息时,会将消息发送给所有连接了当前
endpoint
的浏览器 - 配置WebSocket,需要在配置类上使用
@EnableWebSocketMessageBroker
- 或者通过继承
AbsstractEnableWebSocketMessageBrokerConfigurer
类,重写方法来配置 WebSocket
创建配置类
package com.zyf.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
/**
* Created by zyf on 2018/3/8.
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/endpointZhuang").withSockJS();
}
/**
* 配置消息代理
* @param registry
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
}
}
创建实体数据类bean
package com.zyf.domain;
/**
* Created by zyf on 2018/3/8.
* 浏览器向服务端发送的消息,用此类接收
*/
public class ZyfMessage {
private String name;
public String getName() {
return name;
}
}
package com.zyf.domain;
/**
* Created by zyf on 2018/3/8.
* 服务端向浏览器发消息时,通过此类作为载体传输
*/
public class ZyfResponse {
private String responseMessage;
public ZyfResponse(String responseMessage) {
this.responseMessage = responseMessage;
}
public String getResponseMessage() {
return responseMessage;
}
}
创建控制器
package com.zyf.controller;
import com.zyf.domain.ZyfMessage;
import com.zyf.domain.ZyfResponse;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
/**
* Created by zyf on 2018/3/8.
*/
@Controller
public class ZyfController {
@MessageMapping("/welcome")
@SendTo("/topic/getResponse")
public ZyfResponse say(ZyfMessage zyfMessage) throws InterruptedException {
Thread.sleep(3000);
return new ZyfResponse("Welcome, "+zyfMessage.getName()+"!");
}
}
添加脚本
stomp.min.js
STOMP协议的客户端脚本sockjs.min.js
SockJS的客户端脚本jquery.js
创建演示页面
<!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();">连接</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="@{sockjs.min.js}"></script>
<script th:src="@{stomp.min.js}"></script>
<script th:src="@{jquery.js}"></script>
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
$('#response').html();
}
function connect() {
var socket = new SockJS('/endpointZhuang');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/getResponse', function(respnose){
showResponse(JSON.parse(respnose.body).responseMessage);
});
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendName() {
var name = $('#name').val();
stompClient.send("/welcome", {}, JSON.stringify({ 'name': name }));
}
function showResponse(message) {
var response = $("#response");
response.html(message);
}
</script>
</body>
</html>
运行演示
- 效果:开启三个浏览器窗口,访问
http://localhost:8080/zyf
后,分别连接服务器 - 在任意一个窗口中发送消息到服务端,三秒后,三个窗口都可以接收到从服务端发送来的消息
在谷歌浏览器中,观察STOMP协议的桢