SpringBoot集成WebSocket实现消息推送

简介

​ 目前对于服务端向客户端推送数据,常用技术方案有轮询、websocket等。

轮询的方式比较简单,而且获取的数据不是完全实时的,这里就不介绍了。

websocket特点:

  • WebSocket 是一种双向通信协议,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据;
  • WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

对于一些概念性的东西,这里就不多讲了,网上资料一大堆。简单粗暴直接上代码,springboot集成了websocket,使用起来非常方便。

一、引入依赖

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

我这里用的是2.1.6.RELEASE版本

二、编写websocket配置类

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * @author zzs
 * @date 2020/1/2 15:31
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        /**
         * 注册 Stomp的端点
         * addEndpoint:添加STOMP协议的端点。这个HTTP URL是供WebSocket或SockJS客户端访问的地址
         * withSockJS:指定端点使用SockJS协议
         */
        stompEndpointRegistry.addEndpoint("/websocket-simple")
                .setAllowedOrigins("*")
                .withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        /**
         * 配置消息代理
         * 启动简单Broker,消息的发送的地址符合配置的前缀来的消息才发送到这个broker
         */
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }
}

@EnableWebSocketMessageBroker:此注解表示使用STOMP协议来传输基于消息代理的消息,此时可以在@Controller类中使用@MessageMapping

很简单,里面配置的路径如果看不懂注释没有关系,待会在前端代码中对应上就明白了。

三、编写前后端程序

后端Controller层:

import lombok.extern.slf4j.Slf4j;
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 org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author zzs
 * @date 2020/1/2 15:27
 */
@Slf4j
@Controller
public class BroadcastController {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    /**
     * 该地址 /receive 接收前端发送过来的消息
     * 该地址 /topic/getResponse 是后端要将消息发送到的websocket客户端地址
     *
     * 参数的接收和传递按照springMVC的格式来就行了
     * 
     * @param name
     * @return
     */    
    @MessageMapping("/receive")
    @SendTo("/topic/getResponse")
    public String broadcast(@RequestParam String name) {
        log.info("receive a message = {}", name);
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        return "success: " + sdf.format(now);
    }

    public void send() {
        // 后台主动发送消息
        this.simpMessagingTemplate.convertAndSend("/topic/getResponse", "时间:" + new Date());
    }

}

SimpMessagingTemplate:看到Template后缀就知道,这是spring为我们封装好的模板工具了,当需要后台主动向前端发送消息时,将其注入进来使用即可。

@MessageMapping注解和我们之前使用的@RequestMapping类似。@SendTo注解表示当服务器有消息需要推送的时候, 会对订阅了@SendTo中路径的浏览器发送消息。

l浏览器客户端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="/js/public/jquery-3.4.1.min.js"></script>
    <!-- 这里需要引入这两个websocket相关的js -->
    <script type="text/javascript" src="/js/public/stomp-websocket/stomp.min.js"></script>
    <script type="text/javascript" src="/js/public/sockjs-client/sockjs.min.js"></script>
</head>

<body onload="connect();">
<div>
    <div id="conversationDiv">
        <label>Please input : </label><input type="text" id="name"/>

        <button id="sendName" onclick="sendName();">发送</button>
        <p id="response"></p>
    </div>
</div>

<script type="text/javascript">
    window.onbeforeunload = function () {
        disconnect();
    }

    var stompClient = null;

    function connect() {
        // websocket的连接地址,即WebSocketMessageBrokerConfigurer中registry.addEndpoint("/websocket-simple")配置的地址
        var socket = new SockJS('/websocket-simple');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {
            console.log('Connected: ' + frame);
            // 客户端订阅消息的地址:即服务端使用@SendTo("/topic/getResponse")注解的里配置的值
            stompClient.subscribe('/topic/getResponse', function (response) {
                showResponse(response.body);
            });
        });
    }

    function disconnect() {
        if (stompClient != null) {
            stompClient.disconnect();
        }
    }

    function sendName() {
        var name = $('#name').val();
        // 客户端消息发送的地址:即服务端使用@MessageMapping("/receive")注解的里配置的值
        // 前缀/app是WebSocketMessageBrokerConfigurer中config.setApplicationDestinationPrefixes("/app")配置的值
        stompClient.send("/app/receive", {}, JSON.stringify({'name': name}));
    }

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

Stomp websocket使用socket实现双工异步通信能力。但是如果直接使用websocket协议开发程序比较繁琐,我们可以使用它的子协议Stomp

SockJS sockjs是websocket协议的实现,增加了对浏览器不支持websocket的时候的兼容支持。 SockJS的支持的传输的协议有3类: WebSocket, HTTP Streaming, and HTTP Long Polling。默认使用websocket,如果浏览器不支持websocket,则使用后两种的方式。 SockJS使用"Get /info"从服务端获取基本信息。然后客户端会决定使用哪种传输方式。如果浏览器使用websocket,则使用websocket。如果不能,则使用Http Streaming,如果还不行,则最后使用 HTTP Long Polling

客户端的逻辑很简单,就是在页面加载完成的时候,建立websocket连接,连接的地址即是websocket配置类中的地址,然后订阅指定的地址(上边都有注释),订阅到的消息会显示在页面上;同时页面上又有一个可以主动发送消息到后端的按钮,最后页面销毁时关闭连接。

至此,程序都已编写完成

四、测试

在这里插入图片描述

在这里插入图片描述

可以看到,chrome中发送的消息,后台收到了,而且还推送给了都订阅该地址的客户端,即两个浏览器都收到了推送。

至此,SpringBoot集成Websocket的简单实用已经完成,更深入的研究有待完善。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现Spring Boot集成WebSocket实现消息推送,需要进行以下步骤: 1. 添加Spring Boot WebSocket依赖 2. 创建WebSocket配置类 3. 创建WebSocket处理器类 4. 创建WebSocket拦截器类 5. 创建WebSocket消息模型类 6. 在Spring Boot中使用WebSocket 下面是一个简单的示例代码: 1. 添加Spring Boot WebSocket依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建WebSocket配置类 创建一个WebSocket配置类,用于配置WebSocket相关的参数,如下所示: ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new WebSocketHandler(), "/websocket").addInterceptors(new WebSocketInterceptor()); } } ``` 3. 创建WebSocket处理器类 创建一个WebSocket处理器类,用于处理WebSocket连接、断开连接和接收消息等操作,如下所示: ``` public class WebSocketHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions) { s.sendMessage(message); } } } ``` 4. 创建WebSocket拦截器类 创建一个WebSocket拦截器类,用于拦截WebSocket连接请求,如下所示: ``` public class WebSocketInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } } ``` 5. 创建WebSocket消息模型类 创建一个WebSocket消息模型类,用于封装WebSocket消息,如下所示: ``` public class WebSocketMessage { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } } ``` 6. 在Spring Boot中使用WebSocket 在Spring Boot中使用WebSocket非常简单,只需要在Controller中注入WebSocketSession即可,如下所示: ``` @Controller public class WebSocketController { @Autowired private WebSocketSession session; @MessageMapping("/send") public void send(WebSocketMessage message) throws Exception { session.sendMessage(new TextMessage(message.getContent())); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值