Springboot基于WebSocket实现后端消息推送

  • 由于业务需要,在后台系统中需要添加消息推送功能,于是就去网上查阅相关资料,但是网上的资料都是前后端在一个项目中运行的,现在前后端分离,所以就自己折腾了一下,遇到了很多坑。
  • 代码都是从网上的博客中拷贝过来的,首先是配置文件:
@Configuration
// @EnableWebSocketMessageBroker注解用于开启使用STOMP协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)
// 开始支持@MessageMapping,就像是使用@requestMapping一样。
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer, BaseLoggerService {

    private Session session;

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        //注册一个Stomp的节点(endpoint),并指定使用SockJS协议,其中setAllowedOrigins是设置跨域的
        stompEndpointRegistry.addEndpoint("/webSocketEndPoint").setAllowedOrigins("*").withSockJS();
        // 如果要使用Java代码来连接Websocket需要使用如下配置,这段代码是翻墙去StackOverflow上面找到的,用来测试使用Java代码连接websocket
        // stompEndpointRegistry.addEndpoint("/webSocketEndPoint").setHandshakeHandler(new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy())).setAllowedOrigins("*");
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //服务端发送消息给客户端的域,多个用逗号隔开
        registry.enableSimpleBroker("/topic", "/user");
        //定义一对一推送的时候前缀
        registry.setUserDestinationPrefix("/user");
        //定义websoket前缀
        registry.setApplicationDestinationPrefixes("/ws-push");
    }
}
  • 其次就是websocket发送消息的服务:
@Service
public class WebSocketMessageServiceImpl implements WebSocketMessageService {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    /**
     * 广播
     * 发给所有在线用户
     *
     * @param msg
     */
    public void sendMsg(WebSocketMessage msg) {
        simpMessagingTemplate.convertAndSend("/topic/getResponse", msg);
    }

    /**
     * 发送给指定用户
     *
     * @param users
     * @param msg
     */
    private void send2Users(String users, final Object msg) {
        simpMessagingTemplate.convertAndSendToUser(users, "/msg", msg);
    }

	/**
     * 根据消息类型发送不同的内容
     *
     * @param param
     */
    @Override
    public void sendAndFormatToUsers(Map param) {
         // 发送消息到前端,可以在这里通过自定义字符串向前端发送指定用户发送消息
         String newUser = "webSocket";
         // 点对点发送消息
         send2Users(newUser, message);
         logger.info(message);
    }	
}
  • 前端代码,需要导入三个js文件:
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello topic</title>
    <script src="./sock.js"></script>
    <script src="./stomp.js"></script>
    <script src="./jquery.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() {
            console.log("111111111111");
            // 这里的端口需要写自己项目的端口
            var socket = new SockJS("http://localhost:7086/webSocketEndPoint");
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                // 这里的webSocket与后端的自定义字符串相匹配,用来接收后台发送的指向消息
                stompClient.subscribe('/user/webSocket/msg', 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("/subscribe", {}, JSON.stringify({ 'name': name }));
        }
    </script>
</head>
<body onload="disconnect()">
<noscript><h2 style="color: #ff0000">Seems your browser doesn't 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>
  • 代码都已经准备好了,然后启动Springboot项目,再使用Nginx打开Html页面,我之前没有使用Nginx打开Html访问时,前端会报错,内容如下:

错误信息

  • 发送消息时,自己写个测试类,调用sendAndFormatToUsers方法即可。
  • 之后我想测试websocket的最大连接数,就去网上找了一段java连接websocket的代码:
@ClientEndpoint
public class WebSocketTest {

    private String deviceId;

    private Session session;

    public WebSocketTest () {

    }

    public WebSocketTest (String deviceId) {
        this.deviceId = deviceId;
    }

    protected boolean start() {
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();
        String uri = "ws://localhost:7086/webSocketEndPoint";
        System.out.println("Connecting to " + uri);
        try {
            session = container.connectToServer(WebSocketTest.class, URI.create(uri));
            System.out.println("count: " + deviceId);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static void main(String[] args) {
        for (int i = 1; i< 50000; i++) {
            WebSocketTest wSocketTest = new WebSocketTest(String.valueOf(i));
            if (!wSocketTest.start()) {
                System.out.println("测试结束!");
                break;
            }
        }
    }

}
  • 经过测试,目前项目能支持的最大websocket连接数为10000,完全足够项目使用了,但是通过查阅资料知道,可以通过配置tomcat最大连接数来提高连接数,当将最大连接数配置为20000时可以将连接数提高到16000左右。
发布了24 篇原创文章 · 获赞 14 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/biubiu2it/article/details/86169196