spring 整合websoket(整理)

定義:

  • sockjs.js:  瀏覽器JavaScript庫,它提供了一個相似於網絡的對象。SockJS提供了一個連貫的、跨瀏覽器的Javascript API,它在瀏覽器和web服務器之間建立了一個低延遲、全雙工、跨域通訊通道。html

  • STOMP:簡單(流)文本定向消息協議,它提供了一個可互操做的鏈接格式,容許STOMP客戶端與任意STOMP消息代理(Broker)進行交互。有點像TCP和HTTP之間的關係,在websocket的通訊中,有了STOMP協議後,客戶端和服務端可以以更友好的方式進行交流。若是沒有提供第三方的STOMP代理,好比Rabbitmq等,那麼使用的就是spring容器本身提供的STOMP代理。web

關係:

可以使用sock.js創建websocket的客戶端鏈接。websocket可使用STOMP協議做爲傳輸的協議。spring

樣例代碼以下:json

  • 定義WebSocketMessageBrokerConfigurer,通常是繼承自AbstractWebSocketMessageBrokerConfigurer:
@Configuration
@EnableWebSocketMessageBroker  //在 WebSocket 上啓用 STOMP
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        /**
         * 啓用了STOMP代理中繼功能:並將其目的地前綴設置爲 "/topic";
         * spring就能知道 全部目的地前綴爲"/topic" 的消息都會發送到STOMP代理中;
         */
        config.enableSimpleBroker("/topic", "/user");
        /**
         * 設置了應用的前綴爲"app":全部目的地以"/app"打頭的消息(發送消息url not鏈接url)
         * 都會路由到帶有@MessageMapping註解的方法中,而不會發布到代理隊列或主題中;
         */
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/webSocket").setAllowedOrigins("*").withSockJS();
    }

}
  1. registerStompEndpoints:註冊websocket的端點地址,也就是客戶端鏈接的地址,在上面的配置中,客戶端鏈接的地址是:http://ip:port/項目名/websocket
  2. setAllowedOrigins:上面的代碼中表示是全部的ip地址都可以鏈接,也能夠對固定的地址進行過濾。
  3. sockjs():提供對sockjs訪問的支持。

websocket通常有兩種應用場景:

  • 客戶端訂閱到服務端,這個時候服務端會處理一些客戶端的信息,好比將客戶端的信息註冊到服務端的列表之中。
  • 服務端收到消息後進行推送到客戶端。

上面的配置中:跨域

  • /app:表明客戶端直接發送給服務端的消息,不須要通過stomp消息代理,將由@MessageMapping的直接處理,並返回消息。
    例如:客戶端發送的消息:
stompClient.send("/app/webSocket/updateDevice", {}, JSON.stringify(req));

/app/websockt/send將由下面的代碼來進行處理:瀏覽器

@MessageMapping("/webSocket/send")
    public void updateDevice(SimpMessageHeaderAccessor headerAccessor, String requestContent)
        throws Exception {
        SubscriptionMsg msg = JSON.parseObject(requestContent, SubscriptionMsg.class);
        System.out.println(msg);
    }

STOMP消息代理的配置以下:服務器

config.enableSimpleBroker("/topic", "/user");

客戶端使用stompClient.subscribe("/topic/theme"),將經過STOMP訂閱在這個topic的主題.websocket

  • 發送消息到單個/user通道:
@Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
//        registry.setPathMatcher(new AntPathMatcher("."));//能夠已「.」來分割路徑,看看類級別的@messageMapping和方法級別的@messageMapping
 
        registry.enableSimpleBroker("/topic","/user");
        registry.setUserDestinationPrefix("/user/");
        registry.setApplicationDestinationPrefixes("/app");//走@messageMapping
    }
@RequestMapping("/app")
@Controller
public class WebSocketController {
    @Resource
    private SimpMessagingTemplate simpMessagingTemplate;
 
    @MessageMapping("/hello")
//  @SendTo("/topic/hello")//會把方法的返回值廣播到指定主題(「主題」這個詞並不合適)
    public void toTopic(SocketMessageVo msg , String name) {
        System.out.println(msg.getName()+","+msg.getMsg());
        this.simpMessagingTemplate.convertAndSend("/topic/hello",msg.getName()+","+msg.getMsg());
//      return "消息內容:"+ msg.getName()+"--"+msg.getMsg();
    }
 
    @MessageMapping("/message")
//  @SendToUser("/message")//把返回值發到指定隊列(「隊列」實際不是隊列,而是跟上面「主題」相似的東西,只是spring在SendTo的基礎上加了用戶的內容而已)
    public void toUser(SocketMessageVo msg ) {
        System.out.println(msg.getName()+","+msg.getMsg());
        this.simpMessagingTemplate.convertAndSendToUser("123","/message",msg.getName()+msg.getMsg());
    }
 
    @RequestMapping("/sendMsg")
    public void sendMsg(HttpSession session){
        System.out.println("測試發送消息:隨機消息" +session.getId());
        this.simpMessagingTemplate.convertAndSendToUser("123","/message","後臺具體用戶消息");
    }
}

總結一下:

WebSocketConfig 中配置setApplicationDestinationPrefixes()的消息會被轉發到WebSocketController 中 @MessageMapping 相應方法進行處理。@SendTo("/topic/message") 會把方法的返回值序列化爲json串,而後發送到指定的主題,不用此註解,使用 simpMessagingTemplate.convertAndSend 效果相同;若爲 @SendToUser("/message") 則爲發送到指定的用戶隊列(實際隊列名字爲/user/用戶名/原隊列名),不用此註解,使用 simpMessagingTemplate.convertAndSendToUser() 效果相同;網絡

參考文檔:http://www.javashuo.com/article/p-fiuuyxpu-ed.htmlsession

相關文章
相關標籤/搜索