<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Springboot整合websocket實(shí)現(xiàn)一對(duì)一消息推送和廣播消息推送

          共 13134字,需瀏覽 27分鐘

           ·

          2021-05-21 14:04

          今日推薦
          后端接口如何提高性能?
          16 個(gè)寫(xiě)代碼的好習(xí)慣
          為什么不推薦使用BeanUtils屬性轉(zhuǎn)換工具
          盤(pán)點(diǎn)阿里巴巴 34 個(gè)牛逼 GitHub 項(xiàng)目
          常見(jiàn)代碼重構(gòu)技巧(非常實(shí)用)

          作者:kunm

          segmentfault.com/a/1190000011908831

          springboot基礎(chǔ)環(huán)境

          請(qǐng)參考springboot文檔

          maven依賴
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-websocket</artifactId>
                  </dependency>
          代碼準(zhǔn)備
          準(zhǔn)備常量類
              //webSocket相關(guān)配置
              //鏈接地址
              public static String WEBSOCKETPATHPERFIX = "/ws-push";
              public static String WEBSOCKETPATH = "/endpointWisely";
              //消息代理路徑
              public static String WEBSOCKETBROADCASTPATH = "/topic";
              //前端發(fā)送給服務(wù)端請(qǐng)求地址
              public static final String FORETOSERVERPATH = "/welcome";
              //服務(wù)端生產(chǎn)地址,客戶端訂閱此地址以接收服務(wù)端生產(chǎn)的消息
              public static final String PRODUCERPATH = "/topic/getResponse";
              //點(diǎn)對(duì)點(diǎn)消息推送地址前綴
              public static final String P2PPUSHBASEPATH = "/user";
              //點(diǎn)對(duì)點(diǎn)消息推送地址后綴,最后的地址為/user/用戶識(shí)別碼/msg
              public static final String P2PPUSHPATH = "/msg";
          接收前端消息實(shí)體
          public class WiselyMessage {
              private String name;

              public String getName() {
                  return name;
              }

              public void setName(String name) {
                  this.name = name;
              }
          }
          后臺(tái)發(fā)送消息實(shí)體
          private String responseMessage;

              public WiselyResponse(String responseMessage){
                  this.responseMessage = responseMessage;
              }

              public String getResponseMessage() {
                  return responseMessage;
              }

              public void setResponseMessage(String responseMessage) {
                  this.responseMessage = responseMessage;
              }
          配置websocket
          @Configuration
          // @EnableWebSocketMessageBroker注解用于開(kāi)啟使用STOMP協(xié)議來(lái)傳輸基于代理(MessageBroker)的消息,這時(shí)候控制器(controller)
          // 開(kāi)始支持@MessageMapping,就像是使用@requestMapping一樣。
          @EnableWebSocketMessageBroker
          public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

              @Override
              public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
                  //注冊(cè)一個(gè)Stomp的節(jié)點(diǎn)(endpoint),并指定使用SockJS協(xié)議。
                  stompEndpointRegistry.addEndpoint(Constant.WEBSOCKETPATH).withSockJS();
              }

              @Override
              public void configureMessageBroker(MessageBrokerRegistry registry) {
                  //服務(wù)端發(fā)送消息給客戶端的域,多個(gè)用逗號(hào)隔開(kāi)
                  registry.enableSimpleBroker(Constant.WEBSOCKETBROADCASTPATH, Constant.P2PPUSHBASEPATH);
                  //定義一對(duì)一推送的時(shí)候前綴
                  registry.setUserDestinationPrefix(Constant.P2PPUSHBASEPATH);
                  //定義websoket前綴
                  registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);
              }
          }
          service
          @Service
          public class WebSocketService {

              @Autowired
              private SimpMessagingTemplate template;

              /**
               * 廣播
               * 發(fā)給所有在線用戶
               *
               * @param msg
               */

              public void sendMsg(WiselyResponse msg) {
                  template.convertAndSend(Constant.PRODUCERPATH, msg);
              }

              /**
               * 發(fā)送給指定用戶
               * @param users
               * @param msg
               */

              public void send2Users(List<String> users, WiselyResponse msg) {
                  users.forEach(userName -> {
                      template.convertAndSendToUser(userName, Constant.P2PPUSHPATH, msg);
                  });
              }
          }
          控制器
          @Controller
          public class WsController {

              @Resource
              WebSocketService webSocketService;

              @MessageMapping(Constant.FORETOSERVERPATH)//@MessageMapping和@RequestMapping功能類似,用于設(shè)置URL映射地址,瀏覽器向服務(wù)器發(fā)起請(qǐng)求,需要通過(guò)該地址。
              @SendTo(Constant.PRODUCERPATH)//如果服務(wù)器接受到了消息,就會(huì)對(duì)訂閱了@SendTo括號(hào)中的地址傳送消息。
              public WiselyResponse say(WiselyMessage message) throws Exception {
                  List<String> users = Lists.newArrayList();
                  users.add("d892bf12bf7d11e793b69c5c8e6f60fb");//此處寫(xiě)死只是為了方便測(cè)試,此值需要對(duì)應(yīng)頁(yè)面中訂閱個(gè)人消息的userId
                  webSocketService.send2Users(users, new WiselyResponse("admin hello"));

                  return new WiselyResponse("Welcome, " + message.getName() + "!");
              }
          }
          頁(yè)面
          <!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();">斷開(kāi)連接</button>
              </div>
              <div id="conversationDiv">
                  <label>輸入你的名字</label><input type="text" id="name" />
                  <button id="sendName" onclick="sendName();">發(fā)送</button>
                  <p id="response"></p>
                  <p id="response1"></p>
              </div>
          </div>
          <!--<script th:src="@{sockjs.min.js}"></script>
          <script th:src="@{stomp.min.js}"></script>
          <script th:src="@{jquery.js}"></script>-->

          <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
          <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
          <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
          <script th:inline="javascript">
              var stompClient = null;
              //此值有服務(wù)端傳遞給前端,實(shí)現(xiàn)方式?jīng)]有要求
              var userId = [[${userId}]];

              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('/endpointWisely'); //1連接SockJS的endpoint是“endpointWisely”,與后臺(tái)代碼中注冊(cè)的endpoint要一樣。
                  stompClient = Stomp.over(socket);//2創(chuàng)建STOMP協(xié)議的webSocket客戶端。
                  stompClient.connect({}, function(frame{//3連接webSocket的服務(wù)端。
                      setConnected(true);
                      console.log('開(kāi)始進(jìn)行連接Connected: ' + frame);
                      //4通過(guò)stompClient.subscribe()訂閱服務(wù)器的目標(biāo)是'/topic/getResponse'發(fā)送過(guò)來(lái)的地址,與@SendTo中的地址對(duì)應(yīng)。
                      stompClient.subscribe('/topic/getResponse'function(respnose){
                          showResponse(JSON.parse(respnose.body).responseMessage);
                      });
                      //4通過(guò)stompClient.subscribe()訂閱服務(wù)器的目標(biāo)是'/user/' + userId + '/msg'接收一對(duì)一的推送消息,其中userId由服務(wù)端傳遞過(guò)來(lái),用于表示唯一的用戶,通過(guò)此值將消息精確推送給一個(gè)用戶
                      stompClient.subscribe('/user/' + userId + '/msg'function(respnose){
                          console.log(respnose);
                          showResponse1(JSON.parse(respnose.body).responseMessage);
                      });
                  });
              }


              function disconnect() {
                  if (stompClient != null) {
                      stompClient.disconnect();
                  }
                  setConnected(false);
                  console.log("Disconnected");
              }

              function sendName() {
                  var name = $('#name').val();
                  //通過(guò)stompClient.send()向地址為"/welcome"的服務(wù)器地址發(fā)起請(qǐng)求,與@MessageMapping里的地址對(duì)應(yīng)。因?yàn)槲覀兣渲昧藃egistry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);所以需要增加前綴/ws-push/
                  stompClient.send("/ws-push/welcome", {}, JSON.stringify({ 'name': name }));
              }

              function showResponse(message{
                  var response = $("#response");
                  response.html(message);
              }
              function showResponse1(message{
                  var response = $("#response1");
                  response.html(message);
              }
          </script>

          </body>
          </html>
          測(cè)試


          點(diǎn)擊連接控制臺(tái)輸出

          表示連接成功并且訂閱了兩個(gè)地址

          此時(shí)在文本框內(nèi)輸入任意值,結(jié)果如圖所示則代表成功

          控制臺(tái)中顯示依次為,發(fā)送信息,目標(biāo)長(zhǎng)度內(nèi)容

          此時(shí)服務(wù)端控制器接收到請(qǐng)求

          同時(shí)給指定用戶發(fā)送了消息,所以控制臺(tái)接收到消息

          同時(shí)因?yàn)榭刂破饔凶⒔釦SendTo所以會(huì)向@SendTo的地址廣播消息,客戶端訂閱了廣播地址所有控制臺(tái)顯示接收了消息

          推薦文章


          更多項(xiàng)目源碼

          瀏覽 86
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲视频在线免费观 | 日日撸av | 96精品秘 无码一区二区 | 亚州看片| 在线观看亚洲免费视频 |