SpringBootラーニング-(14)SpringBootでWebSocket接続を確立する(STOMP実装指定されたユーザへのメッセージ送信)

19856 ワード

STOMPインプリメンテーションを使用して、指定されたユーザにメッセージを送信するには、次の手順に従います.
  • pomファイル依存
  • を追加
  • クライアントユーザエンティティクラス
  • を書く.
  • クライアントチャネルブロックアダプタ
  • を書く
  • websocket stomp
  • の構成
  • 書き込み制御層
  • 書き込みクライアント
  • 1.pomファイル依存の追加
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-websocketartifactId>
    dependency>

    2.クライアントユーザーエンティティクラスを書く
    クライアント・ユーザー・エンティティ・クラスをカスタマイズし、クライアントからの情報をカプセル化します.これは、クライアントごとに一意の識別を提供することに相当します.
    package com.ahut.entity;
    
    import java.security.Principal;
    
    /**
     * 
     * @ClassName: User
     * @Description:      
     * @author cheng
     * @date 2017 9 29    3:02:54
     */
    public final class User implements Principal {
    
        private final String name;
    
        public User(String name) {
            this.name = name;
        }
    
        @Override
        public String getName() {
            return name;
        }
    }

    3.書き込みクライアントチャネルブロックアダプタ
    ブロック方式でstompに含まれるユーザ情報を取得し、認証されたユーザ情報を現在のアクセサに設定する
    package com.ahut.websocket;
    
    import java.util.LinkedList;
    import java.util.Map;
    
    import org.springframework.messaging.Message;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
    import org.springframework.messaging.simp.stomp.StompCommand;
    import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
    import org.springframework.messaging.support.ChannelInterceptorAdapter;
    import org.springframework.messaging.support.MessageHeaderAccessor;
    
    import com.ahut.entity.User;
    
    /**
     * 
     * @ClassName: UserInterceptor
     * @Description:           
     * @author cheng
     * @date 2017 9 29    2:40:12
     */
    public class UserInterceptor extends ChannelInterceptorAdapter {
    
        /**
         *      stomp      
         */
        @SuppressWarnings("rawtypes")
        @Override
        public Message> preSend(Message> message, MessageChannel channel) {
            StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
            if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                Object raw = message.getHeaders().get(SimpMessageHeaderAccessor.NATIVE_HEADERS);
                if (raw instanceof Map) {
                    Object name = ((Map) raw).get("name");
                    if (name instanceof LinkedList) {
                        //             
                        accessor.setUser(new User(((LinkedList) name).get(0).toString()));
                    }
                }
            }
            return message;
        }
    }

    4.websocket stompの構成
    package com.ahut.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.messaging.simp.config.ChannelRegistration;
    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;
    
    import com.ahut.websocket.UserInterceptor;
    
    /**
     * 
     * @ClassName: WebSocketStompConfig
     * @Description: springboot websocket stomp  
     * @author cheng
     * @date 2017 9 27    3:45:36
     */
    
    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {
    
        /**
         *   stomp   
         */
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            //     socketJs    ,    webSocketServer,    
            //                
            // http://localhost:8080/webSocketServer
            //       WebSocket  
            registry.addEndpoint("/webSocketServer").setAllowedOrigins("*").withSockJS();
        }
    
        /**
         *       
         */
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
            //   Broker  
            registry.enableSimpleBroker("/queue", "/topic");
            //          (             )
            registry.setApplicationDestinationPrefixes("/app");
            //           (             ),     ,    /user/
            // registry.setUserDestinationPrefix("/user/");
        }
    
        /**
         *             
         */
        @Override
        public void configureClientInboundChannel(ChannelRegistration registration) {
            registration.setInterceptors(createUserInterceptor());
        }
    
        /**
         * 
         * @Title: createUserInterceptor
         * @Description:            spring ioc  
         * @return
         */
        @Bean
        public UserInterceptor createUserInterceptor() {
            return new UserInterceptor();
        }
    
    }

    5.書き込み制御層
    package com.ahut.action;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.messaging.simp.SimpMessagingTemplate;
    import org.springframework.messaging.simp.user.SimpUser;
    import org.springframework.messaging.simp.user.SimpUserRegistry;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import com.ahut.entity.ServerMessage;
    
    /**
     * 
     * @ClassName: WebSocketAction
     * @Description: websocket   
     * @author cheng
     * @date 2017 9 27    4:20:58
     */
    @Controller
    public class WebSocketAction {
    
        private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        //spring         
        @Autowired
        private SimpMessagingTemplate messagingTemplate;
    
        @Autowired
        private SimpUserRegistry userRegistry;
    
        @RequestMapping(value = "/templateTest")
        public void templateTest() {
            logger.info("      :" + userRegistry.getUserCount());
            int i = 1;
            for (SimpUser user : userRegistry.getUsers()) {
                logger.info("  " + i++ + "---" + user);
            }
            //         
            messagingTemplate.convertAndSendToUser("test", "/queue/message", new ServerMessage("         "));
        }
    
    }

    コード解析:SimpUserRegistry接続されたクライアント情報を取得するために使用されるuserRegistry.getUsers()はユーザーリストを返します
    指定したユーザーへのシミュレーション送信、ブラウザアクセス
    localhost:8080/templateTest

    接続ユーザー名としてtestを使用し、/user/queue/messageトピックを購読したクライアントは、サーバからアクティブにプッシュされたメッセージを受信します.
    convertAndSendToUserのソースコードを表示するには、次の手順に従います.
        @Override
        public void convertAndSendToUser(String user, String destination, Object payload, Map headers,
                MessagePostProcessor postProcessor) throws MessagingException {
    
            Assert.notNull(user, "User must not be null");
            user = StringUtils.replace(user, "/", "%2F");
            super.convertAndSend(this.destinationPrefix + user + destination, payload, headers, postProcessor);
        }

    メッセージを見つけることができますconvertAndSendToUser(「test」,「/queue/message」,new ServerMessage(「サーバアクティブプッシュデータ」)最終的に送信される宛先アドレスは次のとおりです.
    /user/test/queue/message

    ユーザー名に"/"が含まれている場合は"%2 F"に置き換えます.
    6.書き込みクライアント
    
    <html>
    
    <head>
        <title>stomptitle>
    head>
    
    <body>
        Welcome<br/><input id="text" type="text" />
        <button onclick="send()">    button>
        <button onclick="subscribe3()">    /user/queue/messagebutton>
        <hr/>
        <div id="message">div>
    body>
    
    <script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js">script>
    <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js">script>
    <script type="text/javascript">
        //       (      )
        var socket = new SockJS("http://localhost:8080/webSocketServer");
    
        //    STOMP          
        var stompClient = Stomp.over(socket);
    
        //       websocket     CONNECT 
        stompClient.connect(
            {
                name: 'test' //        
            },
            function connectCallback(frame) {
                //      (      CONNECTED  )     
                setMessageInnerHTML("    ");
            },
            function errorCallBack(error) {
                //      (      ERROR  )     
                setMessageInnerHTML("    ");
            }
        );
    
        //    
        function subscribe3() {
            stompClient.subscribe('/user/queue/message', function (response) {
                var returnData = JSON.parse(response.body);
                setMessageInnerHTML("/user/queue/message         :" + returnData.responseMessage);
            });
        }
    
        //         
        function setMessageInnerHTML(innerHTML) {
            document.getElementById('message').innerHTML += innerHTML + '
    '
    ; }
    script> html>

    コード分析:クライアントが接続されている場合、ユーザー名を指定する必要があります.
    //       websocket     CONNECT 
    stompClient.connect(
        {
            name: 'test' //        
        },
        function connectCallback(frame) {
            //      (      CONNECTED  )     
                setMessageInnerHTML("    ");
        },
        function errorCallBack(error) {
        //      (      ERROR  )     
        setMessageInnerHTML("    ");
        }
    );

    ユーザーは、自分に送信されたメッセージを受信するには、/user/queue/messageトピックを購読する必要があります.
    まとめ:
    クライアントサブスクリプション:/user/queue/messageサーバプッシュ指定ユーザー:/user/クライアントユーザー名/queue/message