0
点赞
收藏
分享

微信扫一扫

websocket实现实时数据推送,发布订阅重连单点登录功能

前言

随着Web应用程序的不断发展,实时性和交互性成为了用户体验中至关重要的一部分。传统的HTTP协议在处理实时数据传输方面存在一些局限性,而WebSocket作为一种全双工通信协议,为实现实时、高效的消息推送提供了全新的解决方案。

在Web开发领域,消息推送是一项重要的功能,它使得服务器能够将实时更新的信息主动推送给客户端,而不需要客户端频繁地向服务器发送请求。借助于WebSocket技术,开发人员能够轻松构建具有实时交互功能的Web应用程序,例如在线聊天、实时数据监控、多人协作编辑等。

一、前期准备

1、新建项目,结构如下

2、导入依赖
  <!-- websocket 依赖 -->
        <dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- 打印日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.3.8</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

        <!-- ch02 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.14.2</version>
        </dependency>

        <!-- ch03 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.23</version>
        </dependency>
        <!-- 在 spring 4.0 开始支持-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>5.3.23</version>
        </dependency>

        <!-- ch04 -->
        <!-- 如果想要使用 Spring 的消息代理,则添加以下依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>5.3.23</version>
        </dependency>

 每一个依赖的作用:

以上依赖项将会为您的项目引入WebSocket所需的API、日志、简化代码、Servlet支持以及Spring框架的相关模块,让您可以方便地开发基于WebSocket的Web应用程序,并且与Spring框架无缝集成。

3、配置配置类
1)MvcConfig 类
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

让我解释一下它的作用:

总的来说,这段代码配置了Spring MVC,并且使得Spring能够处理静态资源的请求,从而使得静态资源可以被正确地访问和展示。

2)WebSocket 类

@Configuration
// 启用 webSocket 消息代理中间件
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /**
     * 注册一个连接消息中间件的端点( 路径url )
     * @param registry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("broker");
    }

    /**
     * 配置消息代理,主要是设置相关的主题
     * 消息代理是服务中心的核心,spring-websocket 内置了
     * 一个简单的消息代理,但也只能够满足基本要求,如果
     * 需要强大的消息中心的功能,通常都会集成第三方的消息队列
     * 例如:RabbitMQ 等
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 启用 Spring 内置简单的消息代理并设置一个主题(topic)的前缀
        // 用于消息的发布和订阅
        registry.enableSimpleBroker("/news","video");

        // 如果需要集成外部其他的消息代理,使用下面等等方法
        // registry.enableStompBrokerRelay();

    }
}

让我来解释一下它的作用:

总的来说,这段代码配置了Spring WebSocket的消息代理中间件,使得应用程序能够通过WebSocket进行实时的双向通信,同时设置了相关的主题,以便客户端可以订阅并接收相应的消息。

3)AppConfig 类
@Configuration
@ComponentScan(basePackages = "edu.nf.ch04")
@Import({MvcConfig.class,WebSocketConfig.class})
public class AppConfig {
}

让我来解释一下它的作用:

总的来说,这段代码配置了Spring应用程序的整体配置信息,包括了组件扫描的包路径以及导入了其他的配置类,从而将整个应用程序的配置信息整合在一起。

4)WebConfig 类
public class WebConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{AppConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

这段代码是一个典型的Spring Web应用程序的配置类,它继承自AbstractAnnotationConfigDispatcherServletInitializer,用于替代传统的web.xml文件,让我来解释一下它的作用:

总的来说,这段代码配置了Spring Web应用程序的初始化信息,包括加载Web应用程序的配置类、指定DispatcherServlet的映射路径等,从而取代了传统的web.xml文件。

4、封装一个信息类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Message {

    private String content;
    private String sendTime;

}

让我来解释一下使用到的注解和它的作用:

总的来说,这段代码使用了Lombok库的注解来自动生成通用方法和构造方法,从而简化了代码编写。同时,定义了一个简单的Java类Message,用于表示消息对象,包括消息内容和发送时间两个属性。

二、编写 controller 类,实现通知

@RestController
@RequiredArgsConstructor
public class PublishController {

    /**
     * 消息处理模板,用于发布消息
     */
    private final SimpMessagingTemplate template;

    /**
     * 后台发布消息
     * @param message
     */
    @PostMapping("/publish/{topic}/{sub}")
    public void publish(@PathVariable("topic") String topic,@PathVariable("sub")String sub, String message){
        // 创建一个时间
        String sendTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        Message msg = new Message(message,sendTime);

        // 将消息发布到消息代理指定的主题中
        template.convertAndSend("/"+ topic +"/" + sub,msg);
    }

}

这段代码是一个Spring框架中的REST控制器类PublishController,它使用了一些注解和依赖注入,让我来逐步解释:

总的来说,这个PublishController类是一个RESTful风格的控制器,用于处理POST请求,并通过SimpMessagingTemplate向WebSocket消息代理发布消息。

三、编写页面

1、admin.html --- 发送信息后台
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/JQuery文件.txt.js"></script>
</head>
<body>
<h1>后台管理</h1>
<form id="f1">
<select id="topic">
    <option value="sport">体育</option>
    <option value="recreation">娱乐</option>
</select>

<input type="text" name="message" id="message"/>
<input type="button" value="发布">
</form>

<script>
    $(function () {
        $(':button').on('click',function () {
            let param = $('#f1').serialize();
            let subTopic = $('#topic').val();
            // alert(subTopic)
            $.ajax({
                url:'../publish/news/' + subTopic,
                type:'post',
                data:param,
                success:function ( data ) {
                    $('#message').val('');
                }
            })
        })
    })
</script>

</body>
</html>
2、index.html --- 体育栏目
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/JQuery文件.txt.js"></script>
    <script src="js/stomp.min.js"></script>

</head>
<body>
<h1>体育</h1>

<div id="msg">

</div>

<script>
    $(function () {
        // 创建 WebSocket 对象
        var ws = new WebSocket("ws://localhost:8080/broker");

        // 将 WebSocket 包装成 stomp 客户端
        let stompClient = Stomp.over(ws);

        // 连接服务器并订阅消息
        stompClient.connect({},function () {
            // 执行订阅
            stompClient.subscribe('/news/sport',function ( data ) {
                // 接收发布的通知内容
                // alert(data);
                // 取出 stomp 中的 body 部分并解析为 json 对象
                let msg = $.parseJSON(data.body);
                $('#msg').append(msg.sendTime + '<br>');
                $('#msg').append(msg.content + '<br>')
            })
        })
    })
</script>

</body>
</html>

让我来逐行解释上述代码的含义:

总体来说,这段代码的作用是在页面加载后,通过WebSocket连接到服务器,订阅体育新闻频道,并将接收到的消息动态显示在页面上。

2、index2.html --- 娱乐栏目
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/JQuery文件.txt.js"></script>
    <script src="js/stomp.min.js"></script>

</head>
<body>
<h1>娱乐</h1>

<div id="msg">

</div>

<script>
    $(function () {
        // 创建 WebSocket 对象
        var ws = new WebSocket("ws://localhost:8080/broker");

        // 将 WebSocket 包装成 stomp 客户端
        let stompClient = Stomp.over(ws);

        // 连接服务器并订阅消息
        stompClient.connect({},function () {
            // 执行订阅
            stompClient.subscribe('/news/recreation',function ( data ) {
                // 接收发布的通知内容
                // alert(data);
                // 取出 stomp 中的 body 部分并解析为 json 对象
                let msg = $.parseJSON(data.body);
                $('#msg').append(msg.sendTime + '<br>');
                $('#msg').append(msg.content + '<br>')
            })
        })
    })
</script>

</body>
</html>

这部分代码和体育栏目的是一样的。

四、测试

我们每次发送的通知都是实时的通知,在做一些有通知的功能时就能用到这个案例,实时的发布系统通知。

五、gitee 案例

地址:ch04 · qiuqiu/WebSocket-study - 码云 - 开源中国 (gitee.com) 

举报

相关推荐

0 条评论