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

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

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

依赖如下:

<?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 {

    /**
     * #@MessageMapping@RequestMapping类似
     * 监听 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

猜你喜欢

转载自blog.csdn.net/mathew_leung/article/details/102681871