WebSocket的广播式

一 点睛

WebSocket为浏览器和服务端提供了双工异步通信的功能,即浏览器可以向服务端发送消息,服务端也可以向浏览器发送消息。WebSocket需浏览器的支持,但一般目前的主流浏览器都支持。

WebSocket是通过一个socket来实现双工异步通信能力的。但是直接使用WebSocket协议开发程序显得特别烦琐,我们会使用它的子协议STOMP,它是一个更高级别的协议,STOMP协议使用一个基于帧(frame)的格式来定义消息,与HTTP的request和response类似。

二 Spring Boot针对WebSocket提供的自动化配置

Spring Boot对内嵌Tomcat(7或8)、Jetty9和Undertow使用WebSocket提供了支持。配置源代码如下路径:

三 广播式实战代码

1 新建spring boot项目,pom.xml如下

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
</dependencies>

2 配置WebSocket

这里是针对广播式进行的配置,所谓广播式:即服务端有消息时,会将消息发送给所有连接了当前endpoint的浏览器。

配置代码如下:

package com.wisely.ch7_6;

import org.springframework.context.annotation.Configuration;
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;

@Configuration
//该注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping。
@EnableWebSocketMessageBroker
//需要继承AbstractWebSocketMessageBrokerConfigurer类,重写其方法来配置WebSocket
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{

    @Override
    //注册STOMP协议端点函数
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册一个STOMP的endpoint,并映射到指定URL,并指定使用SockJS协议
        registry.addEndpoint("/endpointWisely").withSockJS();
    }


    @Override
    //配置消息代理
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic"); //广播式应该配置一个/topic消息代理
    }

}

3 浏览器向服务端发送的消息用此类承载

package com.wisely.ch7_6.domain;

public class WiselyMessage {
    private String name;

    public String getName(){
        return name;
    }
}

4 服务端向浏览器发送的消息用此类承载

package com.wisely.ch7_6.domain;

public class WiselyResponse {
    private String responseMessage;
    public WiselyResponse(String responseMessage){
        this.responseMessage = responseMessage;
    }
    public String getResponseMessage(){
        return responseMessage;
    }
}

5 编写控制器代码

package com.wisely.ch7_6.web;

import java.security.Principal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;

import com.wisely.ch7_6.domain.WiselyMessage;
import com.wisely.ch7_6.domain.WiselyResponse;

@Controller
public class WsController {

    //当浏览器向服务端发送请求时,通过@MessageMapping映射/welcome这个地址
    //类似于@RequestMapping
    @MessageMapping("/welcome")
    //如果浏览器订阅了@SendTo中的路径,当服务器有消息时,就会向这些浏览器发送消息
    @SendTo("/topic/getResponse")
    public WiselyResponse say(WiselyMessage message) throws Exception {
        Thread.sleep(3000);
        return new WiselyResponse("Welcome, " + message.getName() + "!");
    }
}

6 添加脚本

将stomp.min.js(STOMP协议的客户端脚本)、sockjs.min.js(SockJS的客户端脚本)以及Jquery放置在src/main/resources/static目录下。

7 演示页面

在src/main/resources/templates下新建ws.html,代码如下:

<!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();">断开连接</button>
    </div>
    <div id="conversationDiv">
        <label>输入你的名字</label><input type="text" id="name" />
        <button id="sendName" onclick="sendName();">发送</button>
        <p id="response"></p>
    </div>
</div>
<script th:src="@{sockjs.min.js}"></script>
<script th:src="@{stomp.min.js}"></script>
<script th:src="@{jquery.js}"></script>
<script type="text/javascript">
    var stompClient = null;

    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'); //连接SockJS的endpoint名称为/endpointWisely
        stompClient = Stomp.over(socket);//使用STOMP子协议的WebSocket客户端
        stompClient.connect({}, function(frame) {//连接WebSocket服务端
            setConnected(true);
            console.log('Connected: ' + frame);
            //订阅/topic/getResponse,这个是在控制器的@SendTo注解中定义的
            //一旦该端点方法被调用,订阅者就会收到消息
            stompClient.subscribe('/topic/getResponse', function(respnose){ 
                showResponse(JSON.parse(respnose.body).responseMessage);
            });
        });
    }
    
    
    function disconnect() {
        if (stompClient != null) {
            stompClient.disconnect();
        }
        setConnected(false);
        console.log("Disconnected");
    }

    function sendName() {
        var name = $('#name').val();
        //通过stompClient向/welcome端点发送消息,这个是在控制器的@MessageMapping中定义的
        stompClient.send("/welcome", {}, JSON.stringify({ 'name': name }));
    }

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

8 配置viewController,为ws.html提供便捷的路径映射。

package com.wisely.ch7_6;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class WebMvcConfig  extends WebMvcConfigurerAdapter{
    
     @Override
       public void addViewControllers(ViewControllerRegistry registry) {
           registry.addViewController("/ws").setViewName("/ws");
       }

}

四 运行

1 开启3个浏览器,并都访问http://localhost:8080/ws,分别连接服务器。然后在一个浏览器发送一条消息,其他浏览器也可接收到消息。

2 浏览器消息跟踪

当点击连接,跟踪到的消息为:

当点击发送,跟踪到的消息为:

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值