springboot集成WebSockets廣播消息(推薦)
一 WebScoketS 簡介
RFC 6455 即 webSockets 協(xié)議提供了一種標(biāo)準(zhǔn)化的方式去建立全雙工,雙方面交流的通道在客戶端和服務(wù)端甚至單一的TCP連接中進(jìn)行通信; webSockets 協(xié)議其跟HTTP的tcp協(xié)議不同,但是其設(shè)計(jì)目的是通過HTTP協(xié)議進(jìn)行工作,可以使用40或者443端口和重新使用現(xiàn)有的防火墻規(guī)則;
GET /spring-websocket-portfolio/portfolio HTTP/1.1 Host: localhost:8080 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg== Sec-WebSocket-Protocol: v10.stomp, v11.stomp Sec-WebSocket-Version: 13 Origin: http://localhost:8080
webSockets 的交互是以HTTP協(xié)議開始的,使用Upgrade header 轉(zhuǎn)向使用Upgrade連接;如果非200狀態(tài)成功響應(yīng)就類似于下面的信息;如果WebSocket server 是運(yùn)行在nginx是需要配置WebSocket upgrade requests ;如果是運(yùn)行在云上,需要查閱相關(guān)的云是否支持WebSocket ;
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0= Sec-WebSocket-Protocol: v10.stomp
二 HTTP 和 WebSocket 對比
在HTTP和REST中一個(gè)應(yīng)用需要很多的URLs;應(yīng)用和客戶端是通過 請求和響應(yīng)的風(fēng)格使用這些URLs進(jìn)行交互;服務(wù)端會路由這些請求給基于HTTP 的URL或者方法或者頭進(jìn)行處理;
WebSockets 通常在初始化的時(shí)候就只有一個(gè)鏈接,所有應(yīng)用的消息都是通過相同的TCP連接進(jìn)行流動;這指向一個(gè)完全不同的異步、事件驅(qū)動的消息傳遞體系結(jié)構(gòu)。
WebSocket 是一種低端的協(xié)議,不像HTTP,其不規(guī)定消息中內(nèi)容中任何的語義信息;這意味著其沒有任何方式去路由或者處理這些信息,除非客戶端和服務(wù)端在語義上達(dá)成一致;
WebSocket 客戶端和服務(wù)端其交流是通過使用更加高級的消息協(xié)議(比如STOMP)和基于HTTP握手請求的Sec-WebSocket-Protocol header ;
三 注意事項(xiàng)
WebSockets可以使web頁面具有動態(tài)性和交互性。然而,在許多情況下,Ajax和HTTP流或 long polling(輪詢)可以提供一個(gè)簡單有效的解決方案。HTTP流和polling適用于消息不頻繁的交互,WebSockets適用于消息較頻繁的交互;在 因特網(wǎng)上由于沒有Upgrade header 或者 關(guān)閉了空閑的長鏈接,受限于在你有限的代理可能會將WebSockets的交互排除;
四 websocket配置和依賴
4.1 依賴
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> </parent> <dependencies> <!-- websocket依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- 模板引擎--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>
4.2 配置
/**
* @Author lsc
* @Description <p>websocket配置類 </p>
* @Date 2019/11/12 22:27
*/
//使用STOMP協(xié)議來傳輸基于消息代理的消息,控制器支持在@Controller類中使用@MessageMapping
@EnableWebSocketMessageBroker
@Configurable
@EnableWebSocket
@Component
public class WebConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注冊 Stomp的端點(diǎn)(Endpoint),并且映射指定的url
registry.addEndpoint("/websocket")
.setAllowedOrigins("*") // 添加允許跨域訪問
.withSockJS();// 指定SockJS協(xié)議
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 啟動廣播模式代理,只有符合的的路徑才發(fā)送消息
registry.enableSimpleBroker("/topic");
}
}
五 實(shí)體類
5.1 接受消息實(shí)體
/**
* @Author lsc
* @Description <p> 接受客戶端消息</p>
* @Date 2019/11/12 22:42
*/
public class AcceptMessages {
private String name;
public String getName() {
return name;
}
}
5.2 發(fā)送消息實(shí)體
/**
* @Author lsc
* @Description <p>發(fā)送消息給客戶端 </p>
* @Date 2019/11/12 22:42
*/
public class SendMessages {
private String responseMessage;
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
}
六控制器
/**
* @Author lsc
* @Description <p>websockets 之 廣播式</p>
* @Date 2019/11/12 22:49
*/
@Controller
public class WebSocketsController {
@MessageMapping("/welcome")//類似@RequestMapping,進(jìn)行客戶端請求地址映射
@SendTo("/topic/getResponse")//訂閱了@SendTo中的路徑進(jìn)行發(fā)送消息
public SendMessages broadcast(AcceptMessages acceptMessages){
System.out.println(acceptMessages.getName());
SendMessages sendMessages = new SendMessages();
sendMessages.setResponseMessage("知識追尋者:"+acceptMessages.getName());
return sendMessages;
}
}
七 前端頁面
在 resource目錄下新建templates目錄存放WebSockets.html;在resource目錄下新建static目錄,繼續(xù)在其子目錄下新建js目錄存放sockjs.min.js,stomp.min.js,jquery-3.3.1.min.js;
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>springboot廣播式WebSocket</title>
</head>
<body onload="disconnect()">
<noscript><h2 style="color: #ffff0000;">Sorry,not support the 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();">發(fā)送</button>
<p id="response"></p>
</div>
</div>
<script th:src="@{js/sockjs.min.js}"></script>
<script th:src="@{js/stomp.min.js}"></script>
<script th:src="@{js/jquery-3.3.1.min.js}"></script>
<script type="text/javascript">
var stompClient = null;
// 設(shè)置連接
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() {
// 轉(zhuǎn)向 endpoint 名為websocket
var socket = new SockJS('/websocket');
// 使用ssocket的協(xié)議
stompClient = Stomp.over(socket);
// 連接
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected:' + frame);
// @Sendto 中定義路徑 向目標(biāo)訂閱消息
stompClient.subscribe('/topic/getResponse', function (response) {
showResponse(JSON.parse(response.body).responseMessage);
})
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log('Disconnected');
}
function sendName() {
var name = $('#name').val();
// 控制器@MessageMapping中定義向目標(biāo)發(fā)送消息
stompClient.send("/welcome", {}, JSON.stringify({'name': name}));
}
function showResponse(message) {
$("#response").html(message);
}
</script>
</body>
</html>
八 視圖轉(zhuǎn)發(fā)
當(dāng)客戶端請求地址是localhost:8080/ws,經(jīng)過springmvc視圖轉(zhuǎn)發(fā)器至WebSockets.html;
/**
* @Author lsc
* @Description <p> spingmvc視圖映射轉(zhuǎn)發(fā)</p>
* @Date 2019/11/12 23:35
*/
@Configurable
@Component
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 配置視圖轉(zhuǎn)發(fā)
registry.addViewController("/ws").setViewName("/WebSockets");
}
}
九 效果圖
即一個(gè)瀏覽器發(fā)送消息,其它連接的瀏覽器也能收到消息,即廣播形式;

十 參考文獻(xiàn)
總結(jié)
以上所述是小編給大家介紹的springboot集成WebSockets廣播消息,希望對大家有所幫助!
- SpringBoot集成WebSocket實(shí)現(xiàn)前后端消息互傳的方法
- springboot集成websocket的四種方式小結(jié)
- SpringBoot集成WebSocket【基于純H5】進(jìn)行點(diǎn)對點(diǎn)[一對一]和廣播[一對多]實(shí)時(shí)推送
- SpringBoot集成WebSocket長連接實(shí)際應(yīng)用詳解
- SpringBoot集成WebSocket實(shí)現(xiàn)后臺向前端推送信息的示例
- SpringBoot2.0集成WebSocket實(shí)現(xiàn)后臺向前端推送信息
- 詳解springboot集成websocket的兩種實(shí)現(xiàn)方式
- springboot業(yè)務(wù)功能實(shí)戰(zhàn)之告別輪詢websocket的集成使用
相關(guān)文章
大廠禁止SpringBoot在項(xiàng)目使用Tomcat容器原理解析
這篇文章主要為大家介紹了大廠禁止SpringBoot在項(xiàng)目使用Tomcat原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
使用注解@Validated效驗(yàn)VO參數(shù)是否合規(guī)
這篇文章主要為大家介紹了使用注解@Validated效驗(yàn)VO參數(shù)是否合規(guī)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Flink實(shí)現(xiàn)特定統(tǒng)計(jì)的歸約聚合reduce操作
這篇文章主要介紹了Flink實(shí)現(xiàn)特定統(tǒng)計(jì)的歸約聚合reduce操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02
Spring Boot集成MyBatis實(shí)現(xiàn)通用Mapper的配置及使用
關(guān)于MyBatis,大部分人都很熟悉。MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。這篇文章主要介紹了Spring Boot集成MyBatis實(shí)現(xiàn)通用Mapper,需要的朋友可以參考下2018-08-08
Java中子類調(diào)用父類構(gòu)造方法的問題分析
本篇文章介紹了,Java中子類調(diào)用父類構(gòu)造方法的問題分析。需要的朋友參考下2013-04-04
利用Java搭建個(gè)簡單的Netty通信實(shí)例教程
這篇文章主要給大家介紹了關(guān)于如何利用Java搭建個(gè)簡單的Netty通信,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
Java foreach循環(huán)是否可以修改數(shù)據(jù)的值問題解決方法
最近在做項(xiàng)目的時(shí)候,需要修改一個(gè)數(shù)組里面各個(gè)元素的值,foreach循環(huán)迭代數(shù)組元素時(shí),不能改變數(shù)組元素的值,這篇文章給大家介紹Java foreach循環(huán)是否可以修改數(shù)據(jù)的值的問題及解決方法,感興趣的朋友一起看看吧2024-02-02
解讀@NoArgsConstructor,@AllArgsConstructor,@RequiredArgsConstr
這篇文章主要介紹了解讀@NoArgsConstructor,@AllArgsConstructor,@RequiredArgsConstructor的區(qū)別及在springboot常用地方,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12

