欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springboot1.x整合websocket实现广播式入门

程序员文章站 2022-05-21 21:25:56
...

这几天学习websocket,跟着书本学习一下广播式通信。

我使用的是idea,项目目录如下:

springboot1.x整合websocket实现广播式入门

依赖如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->

    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springboot-websocket-2</artifactId>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
            <scope>provided</scope>
        </dependency>

        <!--servlet支持开启-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <!--<scope>provided</scope>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

springboot启动类什么的简单的就不贴出来丢人了。直接上配置类。

package com.shengxi.config;

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;

/**
 * 开启使用STOMP,用来传输基于代理的消息,此时控制器支持使用
 * 启用@messageMapping 就像使用 @RequestMapping 一样
 *
 * @author yan
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    /**
     * 注册STOMP 协议的节点(endpoint) 并映射到指定的URL
     * 注册一个 STOMP 的 endpoint ,并指定使用 SockJS协议
     *
     * @param registry 注册器
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/endpointLeung").withSockJS();
    }

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

然后是进行信息交互的两个实体类。这里要注意,我是使用了lombok插件的。

package com.shengxi.entity;

import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


/**
 * @author yan
 * 浏览器提交数据实体类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WiselyMessage implements Serializable {
    private String name;
}
package com.shengxi.entity;

import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * @author yan
 * 推送类
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class WiselyResponse implements Serializable {
    private String responseMsg;
}

配置一个Controller进行交互。

package com.shengxi.web;

import com.shengxi.entity.WiselyMessage;
import com.shengxi.entity.WiselyResponse;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author yan
 * 快速访问方案
 */
@Controller
public class WsController {

    /**
     * #@aaa@qq.com类似
     * 监听 welcome路径
     * 向/topic/getResponse发送消息
     *
     * @param message 客户端发回来的信息
     * @return 因为是广播式测试,所以直接返回加工后的信息
     * @throws InterruptedException ex
     */
    @MessageMapping("/welcome")
    @SendTo("/topic/getResponse")
    public WiselyResponse say(WiselyMessage message) throws InterruptedException {
        //暂停一下,模仿网络延时
        Thread.sleep(3000);
        return new WiselyResponse("Welcome, " + message.getName() + "!");
    }

    @GetMapping("/ws")
    public String index() {
        return "/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>
<!--会自动导入 src/main/resources/static 下的静态资源-->
<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() {
        //连接SockJS的endpoint
        //连哪个节点?传入参数确定(是在WebSocketConfig中定义的节点)
        var socket = new SockJS('/endpointLeung');

        //使用STOMP子协议的WebSocket客户端
        stompClient = Stomp.over(socket);

        //连接WebSocket服务端
        stompClient.connect({}, function (frame) {
            setConnected(true);
            console.log('Connected: ' + frame);

            //通过stompClient.subscribe 订阅 /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.send 向 /welcome (目标) 发送消息,
        // 这个是在控制器的 @MessageMapping中定义的
        stompClient.send("/welcome", {}, JSON.stringify({'name': name}));
    }

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

问题:注意js的引用问题。jq如果有数字版本号,可能会引用失败。

源码在本人github。https://github.com/matthew9811/springbootlearn/tree/master/springboot-websocket-2