一、STOMP協議介紹
STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,簡單(流)文本定向消息協議,它提供了一個可互操作的連接格式,允許STOMP客戶端與任意STOMP消息代理(Broker)進行交互。STOMP協議由於設計簡單,易於開發客戶端,因此在多種語言和多種平臺上得到廣泛地應用。
STOMP協議的前身是TTMP協議(一個簡單的基於文本的協議),專爲消息中間件設計。
STOMP是一個非常簡單和容易實現的協議,其設計靈感源自於HTTP的簡單性。儘管STOMP協議在服務器端的實現可能有一定的難度,但客戶端的實現卻很容易。例如,可以使用Telnet登錄到任何的STOMP代理,並與STOMP代理進行交互。
二、SockJS介紹
SockJS 是一個瀏覽器上運行的 JavaScript 庫,如果瀏覽器不支持 WebSocket,該庫可以模擬對 WebSocket 的支持,實現瀏覽器和 Web 服務器之間低延遲、全雙工、跨域的通訊通道。
三、websocket 是什麼?
是一種網絡通信協議,很多高級功能都需要它
四、爲什麼要使用websocket?
已經有了HTTP協議 爲撒還需要使用WebSocket 嘞?
HTTP 是客戶端請求服務端響應數據,但是我們如果想服務端給客戶端發送消息嘞?
於是乎就有了這種協議,客戶端,服務端可以雙向發送消息最典型的就是聊天系統
五、爲什麼需要stomp?
常規的websocket連接和普通的TCP基本上沒區別
所以STOMP在websocket上提供了一中基於幀線路格式(frame-based wire format)
簡單一點,就是在我們的websocket(TCP)上面加了一層協議,使雙方遵循這種協議來發送消息
服務端:/app,這裏訪問服務端,前綴通過設定的方式訪問
用戶:/user,這裏針對的是用戶消息的傳遞,針對於當前用戶進行傳遞。
其他消息:/topic、/queue,這兩種方式。都是定義出來用於訂閱服務端
需求
APP用戶發起申請操作,需要讓後臺管理系統部分人員感知(審覈提醒 消息提示)。
主要側重介紹下 服務器主動推送,由服務端來觸發。
WebSocket 主要能實現的場景
1、網頁聊天室
2、服務器消息實時通知
來吧,展示~
1.導入pom依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.websocket配置 - WebSocketConfig
/**
* 通過EnableWebSocketMessageBroker 開啓使用STOMP協議來傳輸基於代理(message broker)的消息,此時瀏覽器支持使用@MessageMapping 就像支持@RequestMapping一樣。
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
/**
* 基於STOMP協議的WebSocket
* endPoint 註冊協議節點,並映射指定的URl
*
* @param registry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 註冊一個websocket端點,客戶端將使用它連接到我們的websocket服務器。
registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
}
/**
* 註冊相關服務
* 配置消息代理(message broker)
*
* @param registry
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//定義了服務端接收地址的前綴,也即客戶端給服務端發消息的地址前綴
registry.setApplicationDestinationPrefixes("/yifan");
//定義了一個(或多個)客戶端訂閱地址的前綴信息,也就是客戶端接收服務端發送消息的前綴信息
registry.enableSimpleBroker("/topic", "/user");
// 點對點使用的訂閱前綴(客戶端訂閱路徑上會體現出來),不設置的話,默認也是/user/
registry.setUserDestinationPrefix("/user/");
}
}
介紹以上幾個相關的註解和方法:
- @EnableWebSocketMessageBroker:開啓使用STOMP協議來傳輸基於代理(message broker)的消息,這時控制器支持使用@MessageMapping,就像使用@RequestMapping一樣。
- AbstractWebSocketMessageBrokerConfigurer:繼承WebSocket消息代理的類,配置相關信息。
- registry.addEndpoint("/endpointOyzc").setAllowedOrigins("*").withSockJS(); 添加一個訪問端點“/endpointGym”,客戶端打開雙通道時需要的url,允許所有的域名跨域訪問,指定使用SockJS協議。
- registry.enableSimpleBroker("/topic","/user"); 配置一個/topic廣播消息代理和“/user”一對一消息代理
- registry.setUserDestinationPrefix("/user");點對點使用的訂閱前綴(客戶端訂閱路徑上會體現出來),不設置的話,默認也是/user/
3.產生一個消息
@Controller
//@RequestMapping("/yifan/{user}")
@RequestMapping("yifan")
public class ChatController {
@Autowired
private SimpMessagingTemplate template;
/* 接收消息 @SendToUser 誰發送的返回給誰 */
@MessageMapping("/chatTo")
public void apply(SocketMessage message){
/* 發送給個人*/
// template.convertAndSendToUser(userDO.toString(), "/topic/notifications", "新消息:" + notify.getTitle());
/* 發送給全部*/
template.convertAndSend("/topic/getResponse", new Response("客戶xxx發起申請,請及時處理!" ));
}
@MessageMapping("/chatTo") // 瀏覽器發送請求通過@messageMapping 映射/welcome 這個地址。
@SendTo("/topic/getResponse") // 服務器端有消息時,會訂閱@SendTo 中的路徑的瀏覽器發送消息。
public Response say(Message message) throws Exception {
Thread.sleep(1000);
return new Response("Welcome, " + message.getName() + "!");
}
}
4.客戶端 網頁
需要準備
- jquery.min.js https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js
- sockjs.min.js sockjs
- stomp.js stomp
<script type="text/javascript">
var stompClient = null;
$(function () {
connect();
});
function connect() {
//連接SockJS的endpoint名稱爲"endpointOyzc"
var sock = new SockJS("/endpointChat");
var stomp = Stomp.over(sock);
stomp.connect('guest', 'guest', function(frame) {
/**
訂閱了/user/queue/notifications 發送的消息,這裏雨在控制器的 convertAndSendToUser 定義的地址保持一致,
* 這裏多用了一個/user,並且這個user 是必須的,使用user 纔會發送消息到指定的用戶。
* */
stomp.subscribe("/user/queue/notifications", handleNotification);
stomp.subscribe('/topic/getResponse', function (response) { //訂閱/topic/getResponse 目標發送的消息。這個是在控制器的@SendTo中定義的。
toastr.options = {
"closeButton": true,
"debug": false,
"progressBar": true,
"positionClass": "toast-bottom-right",
"onclick": null,
"showDuration": "400",
"hideDuration": "1000",
"timeOut": "7000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
toastr.info(JSON.parse(response.body).responseMessage);
});
});
function handleNotification(message) {
wrapper.notify();
toastr.info(message.body);
}
}
</script>
分享參考文章:
https://blog.csdn.net/zhou4700219/article/details/53518788