实现基于Spring Boot和WebSockets的实时通讯应用

大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

实时通讯应用在现代互联网服务中越来越重要。使用WebSocket可以实现客户端和服务器之间的双向通讯,从而大大提高实时性。本文将介绍如何使用Spring Boot和WebSockets构建一个简单的实时通讯应用。

项目结构

首先,我们需要搭建一个Spring Boot项目。可以使用Spring Initializr来快速生成项目结构,选择如下依赖:

  • Spring Web
  • Spring WebSocket
  • Spring Boot DevTools

WebSocket配置

创建WebSocket配置类来配置WebSocket端点和消息处理器:

package cn.juwatech.websocket;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

这里我们启用了简单的消息代理,并将应用程序目的地前缀设置为/app。WebSocket端点注册为/ws,并启用了SockJS以便在WebSocket不可用时回退到其他通信方式。

消息处理器

创建一个控制器来处理WebSocket消息:

package cn.juwatech.websocket;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class ChatController {

    @MessageMapping("/message")
    @SendTo("/topic/messages")
    public ChatMessage sendMessage(ChatMessage message) {
        return message;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

在这个控制器中,我们定义了一个处理方法sendMessage,该方法接受来自/app/message目的地的消息,并将响应发送到/topic/messages目的地。

消息类

定义一个消息类来表示聊天消息:

package cn.juwatech.websocket;

public class ChatMessage {
    private String from;
    private String text;

    public ChatMessage() {
    }

    public ChatMessage(String from, String text) {
        this.from = from;
        this.text = text;
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

前端页面

创建一个简单的HTML页面来测试我们的WebSocket实时通讯:

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Chat</title>
    <script src="https://cdn.jsdelivr.net/sockjs/1.0.3/sockjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/stompjs/lib/stomp.min.js"></script>
    <script>
        var stompClient = null;

        function connect() {
            var socket = new SockJS('/ws');
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function (frame) {
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/messages', function (messageOutput) {
                    showMessage(JSON.parse(messageOutput.body));
                });
            });
        }

        function sendMessage() {
            var from = document.getElementById('from').value;
            var text = document.getElementById('text').value;
            stompClient.send("/app/message", {}, JSON.stringify({'from': from, 'text': text}));
        }

        function showMessage(message) {
            var response = document.getElementById('response');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            p.appendChild(document.createTextNode(message.from + ": " + message.text));
            response.appendChild(p);
        }

        window.onload = function() {
            connect();
        };
    </script>
</head>
<body>
    <div>
        <input type="text" id="from" placeholder="Your name" />
        <input type="text" id="text" placeholder="Say something" />
        <button onclick="sendMessage()">Send</button>
        <div id="response"></div>
    </div>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.

这个页面包含一个简单的表单,用于输入消息和发送消息。通过SockJS和STOMP进行WebSocket连接,并处理消息的发送和接收。

运行应用

确保你的Spring Boot应用程序已经启动,打开浏览器访问index.html页面。输入用户名和消息内容,点击发送按钮即可看到实时的消息通讯效果。

扩展功能

在实际应用中,可能还需要实现更多功能,如用户身份验证、消息持久化、群聊和私聊等。可以通过以下方式扩展:

  • 身份验证:使用Spring Security进行用户身份验证和授权。
  • 消息持久化:将消息存储到数据库,如MySQL或MongoDB。
  • 群聊和私聊:扩展WebSocket配置和消息处理器,实现不同的聊天模式。

以下是一个扩展的示例,展示如何在WebSocket消息中添加用户身份验证:

package cn.juwatech.websocket;

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.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketSecurityConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new AuthChannelInterceptorAdapter());
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.

这个配置类中,我们添加了一个自定义的消息通道拦截器,用于处理消息中的身份验证逻辑。

通过本文的介绍,我们实现了一个基于Spring Boot和WebSockets的实时通讯应用,包括WebSocket配置、消息处理器、消息类、前端页面和扩展功能等方面。这些技术和方法可以帮助我们构建高效、可靠的实时通讯应用。