首页 > 编程语言 > 详细

springboot 集成websocket 简单实现

时间:2020-05-08 14:34:18      阅读:55      评论:0      收藏:0      [点我收藏+]

maven依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-thymeleaf</artifactId>
        </dependency>

 

配置文件

server:
  port: 80

#添加Thymeleaf配置
thymeleaf:
  cache: false
  prefix: classpath:/templates/
  suffix: .html
  mode: HTML5
  encoding: UTF-8
  content-type: text/html

 

配置文件

package com.example.admin.config;

import com.example.admin.utils.UserInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
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;

/**
 * @Description:
registerStompEndpoints(StompEndpointRegistry registry)
configureMessageBroker(MessageBrokerRegistry config)
这个方法的作用是定义消息代理,通俗一点讲就是设置消息连接请求的各种规范信息。
registry.enableSimpleBroker("/topic")表示客户端订阅地址的前缀信息,也就是客户端接收服务端消息的地址的前缀信息(比较绕,看完整个例子,大概就能明白了)
registry.setApplicationDestinationPrefixes("/app")指服务端接收地址的前缀,意思就是说客户端给服务端发消息的地址的前缀
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    //    这个方法的作用是添加一个服务端点,来接收客户端的连接。
//    registry.addEndpoint("/socket")表示添加了一个/socket端点,客户端就可以通过这个端点来进行连接。
//    withSockJS()的作用是开启SockJS支持,
    //        setAllowedOrigins 跨域问题
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册两个STOMP的endpoint,分别用于广播和点对点

        registry.addEndpoint("/webServer").setAllowedOrigins("*").withSockJS();
        registry.addEndpoint("/queueServer").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //表示客户端订阅地址的前缀信息,也就是客户端接收服务端消息的地址的前缀信息,topic用来广播,user用来实现p2p
        registry.enableSimpleBroker("/topic", "/user");
        //指服务端接收地址的前缀,意思就是说客户端给服务端发消息的地址的前缀
        registry.setApplicationDestinationPrefixes("/app");
        //registry.setUserDestinationPrefix("/user");这句话表示给指定用户发送一对一的主题前缀是"/user"。
    }

    /**
     * 配置客户端入站通道拦截器
     */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(userInterceptor());
    }

    /**
     * @return
     * @Title: createUserInterceptor
     * @Description: 将客户端渠道拦截器加入spring ioc容器
     */
    @Bean
    public UserInterceptor userInterceptor() {
        return new UserInterceptor();

    }
}

 

获取用户信息

package com.example.admin.utils;

import com.example.admin.model.User;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
import org.springframework.messaging.support.MessageHeaderAccessor;

import java.util.LinkedList;
import java.util.Map;

public class UserInterceptor extends ChannelInterceptorAdapter {
    /**
     * 获取包含在stomp中的用户信息
     */
    @SuppressWarnings("rawtypes")
    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        if (StompCommand.CONNECT.equals(accessor.getCommand())) {
            Object raw = message.getHeaders().get(SimpMessageHeaderAccessor.NATIVE_HEADERS);
            if (raw instanceof Map) {
                Object name = ((Map) raw).get("name");
                if (name instanceof LinkedList) {
                    // 设置当前访问器的认证用户
                    accessor.setUser(new User(((LinkedList) name).get(0).toString()));
                }
            }
        }
        return message;
    }

}

 

 

控制器

package com.example.admin.web;

import com.example.admin.model.ReceiveMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.user.SimpUser;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/restful")
public class RestFulController {

    @Autowired
    public SimpMessagingTemplate template;


    @Autowired
    private SimpUserRegistry userRegistry;
    /**
     * @Description:广播
     * @Author:hui.yunfei@qq.com
     * @Date: 2019/6/4
     */
    @MessageMapping("/subscribe")
    //@SendTo
    public void subscribe(ReceiveMessage rm) {
        System.out.println("服务端接收到广播消息:"+rm);
        for(int i =1;i<=5;i++) {
            //广播使用convertAndSend方法,第一个参数为目的地,和js中订阅的目的地要一致
            template.convertAndSend("/topic/getResponse", rm.getMsg());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * @Description:点对点
     * @Author:hui.yunfei@qq.com
     * @Date: 2019/6/4
     */
    @MessageMapping("/queue")
    //@SendToUser
    public void queue(ReceiveMessage rm) {
        System.out.println("服务端接收到点对点消息:"+rm);
        for(int i =1;i<=5;i++) {
            /*广播使用convertAndSendToUser方法,第一个参数为用户id,此时js中的订阅地址为
            "/user/" + 用户Id + "/message",其中"/user"是固定的*/
            template.convertAndSendToUser(rm.getUser(),"/message",rm.getMsg());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * @Description:主动推消息到客户端(可配做定时器)
     * @Author:hui.yunfei@qq.com
     * @Date: 2019/6/4
     */

    @RequestMapping("/send")
    public void send(){
        template.convertAndSend("/topic/getResponse", "我是服务器主动推送的消息");
    }

    @RequestMapping("/getOnline")
    @ResponseBody
    public void getOnline(){
        System.out.println("当前在线人数:" + userRegistry.getUserCount());
        int i = 1;
        for (SimpUser user : userRegistry.getUsers()) {
            System.out.println("用户" + i++ + "---" + user);
        }
    }
}

 

页面

<html>
<head>
    <meta charset="UTF-8">
    <title>Hello topic</title>
    <script src="sockjs.min.js"></script>
    <script src="stomp.min.js"></script>
    <script src="jquery-3.2.1.min.js"></script>
    <script type="text/javascript">
        var stompClient = null;
        function setConnected(connected){
            document.getElementById("connect").disabled = connected;
            document.getElementById("disconnect").disabled = !connected;
            $("#response").html();
        }
        function connect() {
            var socket = new SockJS("/webServer");
            stompClient = Stomp.over(socket);
            stompClient.connect({name:yunfei}, function(frame) {
                setConnected(true);
                console.log(Connected:  + frame);
                stompClient.subscribe(/topic/getResponse, function(response){
                    var response1 = document.getElementById(response);
                    var p = document.createElement(p);
                    p.style.wordWrap = break-word;
                    p.appendChild(document.createTextNode(response.body));
                    response1.appendChild(p);
                });
            });
        }

        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            console.log("Disconnected");
        }

        function sendName() {
            var name = document.getElementById(name).value;
            console.info(1111111111);
            stompClient.send("/app/subscribe", {}, JSON.stringify({ msg: name }));
        }
    </script>
</head>
<body onload="disconnect()">
<noscript><h2 style="color: #ff0000">Seems your browser doesnt support Javascript! Websocket relies on Javascript being enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div>
    <div>
        <button id="connect" onclick="connect();">Connect</button>
        <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
    </div>
    <div id="conversationDiv">
        <labal>名字</labal><input type="text" id="name" />
        <button id="sendName" onclick="sendName();">Send</button>
        <p id="response"></p>
    </div>
</div>

</body>
</html>

 

 

<html>
<head>
    <meta charset="UTF-8">
    <title>Hello queue</title>
    <script src="sockjs.min.js"></script>
    <script src="stomp.min.js"></script>
    <script src="jquery-3.2.1.min.js"></script>
    <script type="text/javascript">
        var stompClient = null;
        function setConnected(connected){
            document.getElementById("connect").disabled = connected;
            document.getElementById("disconnect").disabled = !connected;
            $("#response").html();
        }
        function connect() {
            var socket = new SockJS("/queueServer");
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log(Connected:  + frame);
                stompClient.subscribe(/user/+document.getElementById(user).value+/message, function(response){
                    var response1 = document.getElementById(response);
                    var p = document.createElement(p);
                    p.style.wordWrap = break-word;
                    p.appendChild(document.createTextNode(response.body));
                    response1.appendChild(p);
                });
            });
        }

        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            console.log("Disconnected");
        }

        function sendName() {
            var name = document.getElementById(name).value;
            var user = document.getElementById(user).value;
            console.info(1111111111);
            stompClient.send("/app/queue", {}, JSON.stringify({ msg: name,user:user}));
        }
    </script>
</head>
<body onload="disconnect()">
<noscript><h2 style="color: #ff0000">Seems your browser doesnt support Javascript! Websocket relies on Javascript being enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div>
    <div>
        <labal>用户</labal><input type="text" id="user" />
        <button id="connect" onclick="connect();">Connect</button>
        <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
    </div>
    <div id="conversationDiv">
        <labal>名字</labal><input type="text" id="name" />
        <button id="sendName" onclick="sendName();">Send</button>
        <p id="response"></p>
    </div>
</div>

</body>
</html>

 

springboot 集成websocket 简单实现

原文:https://www.cnblogs.com/jerry-wei/p/12849285.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!