spring websocket + stomp 實現廣播通訊和一對一通訊<轉>

spring對於基於stomp協議的websocket通訊,其官網上面有一個guide,可是根據guide你只能寫出來廣播方式的通訊,不能實現一對一的通訊,這篇文章在這裏把廣播和一對一一塊兒整理一下給你們。javascript

服務端:html

一,依賴,spring-websocket和spring-messaging,這裏給出maven方式:java

 

[html]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. <dependency>  
  2.             <groupId>org.springframework</groupId>  
  3.             <artifactId>spring-websocket</artifactId>  
  4.             <version>${spring-core.version}</version>  
  5.         </dependency>  
  6.         <dependency>  
  7.             <groupId>org.springframework</groupId>  
  8.             <artifactId>spring-messaging</artifactId>  
  9.             <version>${spring-core.version}</version>  
  10.         </dependency>  


二,服務端代碼:web

 

服務端的初始化,只須要兩個類:WebsocketConfig和WebSocketControllerspring

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. import org.springframework.context.annotation.Configuration;  
  2. import org.springframework.messaging.simp.config.MessageBrokerRegistry;  
  3. import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;  
  4. import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;  
  5. import org.springframework.web.socket.config.annotation.StompEndpointRegistry;  
  6.   
  7. @Configuration  
  8. @EnableWebSocketMessageBroker  
  9. public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {  
  10.   
  11.     @Override  
  12.     public void configureMessageBroker(MessageBrokerRegistry config) {  
  13.         config.enableSimpleBroker("/topic","/user");  
  14.         config.setApplicationDestinationPrefixes("/app");  
  15.         config.setUserDestinationPrefix("/user/");  
  16.     }  
  17.   
  18.     @Override  
  19.     public void registerStompEndpoints(StompEndpointRegistry registry) {  
  20.         registry.addEndpoint("/webServer").withSockJS();  
  21.     }  
  22.   
  23. }  

 

 

這個類表示啓用websocket消息處理,以及收發消息的域json

config.enableSimpleBroker("/topic","/user");這句表示在topic和user這兩個域上能夠向客戶端發消息;config.setUserDestinationPrefix("/user/");這句表示給指定用戶發送(一對一)的主題前綴是「/user/」;  config.setApplicationDestinationPrefixes("/app"); 這句表示客戶端向服務端發送時的主題上面須要加"/app"做爲前綴;registry.addEndpoint("/webServer").withSockJS();這個和客戶端建立鏈接時的url有關,後面在客戶端的代碼中能夠看到。websocket


下面是一個spring風格的controller,用於接收客戶端的消息及響應客戶端:session

 

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. import org.springframework.beans.factory.annotation.Autowired;  
  2. import org.springframework.messaging.handler.annotation.MessageMapping;  
  3. import org.springframework.messaging.handler.annotation.SendTo;  
  4. import org.springframework.messaging.simp.SimpMessagingTemplate;  
  5. import org.springframework.messaging.simp.annotation.SendToUser;  
  6. import org.springframework.stereotype.Controller;  
  7.   
  8. @Controller  
  9. public class WebSocketController {  
  10.   
  11.     public SimpMessagingTemplate template;  
  12.   
  13.     @Autowired  
  14.     public WebSocketController(SimpMessagingTemplate template) {  
  15.         this.template = template;  
  16.     }  
  17.   
  18.     @MessageMapping("/hello")  
  19.     @SendTo("/topic/hello")  
  20.     public Greeting greeting(Greeting message) throws Exception {  
  21.         return message;  
  22.     }  
  23.   
  24.     @MessageMapping("/message")  
  25.     @SendToUser("/message")  
  26.     public UserMessage userMessage(UserMessage userMessage) throws Exception {  
  27.         return userMessage;  
  28.     }  
  29.   
  30. }  

這個類裏面織入SimpMessagingTemplate對象,後面動態發送消息時,須要用到這個對象。app

 

第一個方法,表示服務端能夠接收客戶端經過主題「/app/hello」發送過來的消息,客戶端須要在主題"/topic/hello"上監聽並接收服務端發回的消息socket

第二個方法道理相同,只是注意這裏用的是@SendToUser,這就是發送給單一客戶端的標誌。本例中,客戶端接收一對一消息的主題應該是「/user/」 + 用戶Id + 「/message」 ,這裏的用戶id能夠是一個普通的字符串,只要每一個用戶端都使用本身的id而且服務端知道每一個用戶的id就行。

這裏的Greeting和UserMessage是一個普通的實現了序列化的Java bean

就這樣,那麼,在程序中的其餘地方要動態發送消息,就是下面這兩句代碼:

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. webSocketController.template.convertAndSend("/topic/hello",greeting) //廣播  
  2. webSocketController.template.convertAndSendToUser(userId, "/message",userMessage) //一對一發送,發送特定的客戶端  

 

 

 

 

客戶端:

js客戶端須要導入兩個js組件:sockjs-0.3.4.js,stomp.js

 

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. var url = 'http://localhost:8080/appRoot/webServer'  
  2. var socket = new SockJS(url, undefined, {protocols_whitelist: ['websocket']});  
  3. var stompClient = Stomp.over(socket);  
  4. stompClient.connect({}, function(frame) {  
  5.     stompClient.subscribe('/topic/hello', function(message){  
  6.         var json = JSON.parse(message.body);  
  7.     });  
  8.   
  9.      stompClient.subscribe('/user/' + userId + '/message', function(message){  
  10.          var messageEntity = JSON.parse(message.body);  
  11.     });  
  12. });  

 

第一個subscribe,是接收廣播消息,第二個是接收一對一消息,其主題是'/user/' + userId+ '/message' , 不一樣客戶端具備不一樣的userId

看到這裏,你會發現,這裏所謂的一對一,只是業務層面的一對一,也就是,須要不一樣客戶端具備不一樣的userId才能實現,若是兩個客戶端使用相同的userid, 那麼服務端給這個userId發送消息時,這兩個客戶端都會收到。要真正實現websocket技術層面的一對一發送,那就要使用websocket的session了。關於session方式,我這裏上傳一個demo,有興趣能夠下載:http://download.csdn.net/detail/valenon/8725195

相關文章
相關標籤/搜索