springboot+websocket实现页面后台长连接

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xm526489770/article/details/81030895

    在自己整合websocket时踩了一些坑,给大家分享出来希望可以帮到有需要的小伙伴,我的测试案例中有什么问题请指出,大家共同学习,现在开始上代码;

第一步,添加pom.xml依赖

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>zenithink-demo</groupId>
    <artifactId>zenithink-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <com.alibaba.dubbo.version>2.5.3</com.alibaba.dubbo.version>
        <dubbo-spring-boot>1.0.0</dubbo-spring-boot>
        <org.apache.zookeeper.version>3.4.6</org.apache.zookeeper.version>
        <com.github.sgroschupf.zkclient.version>0.1</com.github.sgroschupf.zkclient.version>
    </properties>

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

        <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>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
        </dependency>

        <!--Http client组件-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.5</version>
        </dependency>
        <!--json对象依赖-->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>
        <!--字符串工具依赖-->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <!--日志依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.6</version>
        </dependency>
        <!--spring data mongodb-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>


        <!--引入websocket依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>lombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>


</project>

第二步,添加所需封装实体类

public class SocketMessage {

    public String message;

    public String date;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
}

第三步,websochet配置对象

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;

/**
 * websocket设置
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        //设置浏览器接收的服务前缀,同时也是后台服务推送的前缀
        config.enableSimpleBroker("/topic");
        //设置浏览器发送消息的服务前缀,也就是后台服务接收前台信息的前缀
        config.setApplicationDestinationPrefixes("/app");
    }

    //添加服务端点 浏览器链接这个地址
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/my-websocket").withSockJS();
    }

}

第四步,添加前端控制器

import com.demo.entity.SocketMessage;
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.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * websocket测试前端控制器
 */
@Controller
public class App {

    /**
     * websochet消息发送对象
     */
    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    /**
     * 跳转到测试页面
     * @return
     */
    @GetMapping("/")
    public String index() {
        return "test01";
    }

    //测试页面显示后台消息推送次数
    private int count=0;

    //接收浏览器消息路径设置
    @MessageMapping("/send")
    //服务端向浏览器推送地址设置
    @SendTo("/topic/send")
    public SocketMessage send(SocketMessage message) throws Exception {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        message.date = "浏览器消息";
        return message;
    }

    //由后台发送到浏览器服务
    @SendTo("/topic/callback")
    //定时5秒给页面推一次数据
    @Scheduled(cron="0/5 * * * * ?")
    public Object callback() throws Exception {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("推送消息了"+df.format(new Date()));
        //向页面这个地址推送消息
            messagingTemplate.convertAndSend("/topic/callback","客户端消息"+count );
            count++;
        return null;
    }
}

第五步,添加测试页面

扫描二维码关注公众号,回复: 3926671 查看本文章
<!DOCTYPE html>
<html>
<head>
    <title>spring boot——websocket测试页面</title>
    <script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
    <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
    <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
    <script type="text/javascript">


        var stompClient = null;

        var app = angular.module('app', []);
        app.controller('MainController', function($rootScope, $scope, $http) {

            $scope.data = {
                //连接状态
                connected : false,
                //消息
                message : '',
                rows : []
            };

            //连接
            $scope.connect = function() {
                //特别注意链接的IP和浏览器访问地址必须保持一致,不然就会出现链接不上的问题
               var socket = new SockJS('http://10.0.0.253:1214/my-websocket');
                stompClient = Stomp.over(socket);
                stompClient.connect({}, function(frame) {
                    // 接收后台服务推送消息
                    stompClient.subscribe('/topic/send', function(msg) {
                        $scope.data.rows.push(JSON.parse(msg.body));
                        $scope.data.connected = true;
                        $scope.$apply();
                    });
                    // 接收后台服务推送消息
                    stompClient.subscribe('/topic/callback', function(r) {
                        $scope.data.time = '当前服务器推送内容:' + r.body;
                        $scope.data.connected = true;
                        $scope.$apply();
                    });

                    $scope.data.connected = true;
                    $scope.$apply();
                });
            };

            $scope.disconnect = function() {
                if (stompClient != null) {
                    stompClient.disconnect();
                }
                $scope.data.connected = false;
            }
            //浏览器向后台推送消息
            $scope.send = function() {
                stompClient.send("/app/send", {}, JSON.stringify({
                    'message' : $scope.data.message
                }));
            }
        });
        /*]]>*/
    </script>
</head>
<body ng-app="app" ng-controller="MainController">



<label>WebSocket连接状态:</label>
<button type="button" ng-disabled="data.connected" ng-click="connect()">连接</button>
<button type="button" ng-click="disconnect()"
        ng-disabled="!data.connected">断开</button>
<br />
<br />
<div ng-show="data.connected">
    <label>{{data.time}}</label> <br /> <br /> <input type="text"
                                                      ng-model="data.message" placeholder="请输入内容..." />
    <button ng-click="send()" type="button">发送</button>
    <br /> <br /> 消息列表: <br />
    <table>
        <thead>
        <tr>
            <th>接收浏览器内容</th>
            <th>后台推送内容</th>
        </tr>
        </thead>
        <tbody>
        <tr ng-repeat="row in data.rows">
            <td>{{row.message}}</td>
            <td>{{row.date}}</td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>

第六步,页面效果展示

总结:

    到这就算大功告成,不过链接后台服务的时候折腾了很久,最终发现,通过sockjs链接的时候不加IP端口"/my-websocket"链接是可以的,如果改成"127.0.0.1:1214/my-websocket"这样就链接不成功,后来改成"http://127.0.0.1:1214/my-websocket"又可以,通过"ws://127.0.0.1:1214/my-websocket"这样也是链接不通的,总之,浏览器访问地址和页面链接后台地址保持一致就可以了!

猜你喜欢

转载自blog.csdn.net/xm526489770/article/details/81030895