Bootstrap

Spring Boot 中的 @SendTo 注解

Spring Boot 中的 @SendTo 注解

在 Spring Boot 中,@SendTo 注解是一个非常有用的注解,它可以用于实现 WebSocket 的消息转发功能。本文将介绍 @SendTo 注解的原理、使用方法和示例代码。

在这里插入图片描述

什么是 @SendTo 注解

@SendTo 注解是 Spring Boot 中用于将消息发送到指定目的地的注解。它可以用于 WebSocket 中的消息转发功能,将客户端发送的消息转发到指定的目的地,让指定的客户端接收到消息。

@SendTo 注解的原理

@SendTo 注解的原理是利用了 WebSocket 中的消息订阅和发布机制。在 WebSocket 中,每个客户端都可以订阅指定的目的地,当有消息发布到该目的地时,所有订阅该目的地的客户端都会收到该消息。

@SendTo 注解可以将消息发送到指定的目的地,让订阅该目的地的客户端接收到消息。在发送消息时,@SendTo 注解会将消息封装成一个 Message 对象,并将其发送到指定的目的地。客户端在订阅该目的地时,就可以接收到该消息。

如何使用 @SendTo 注解

使用 @SendTo 注解非常简单,只需要在方法上添加该注解,并指定需要发送到的目的地即可。下面是一个使用 @SendTo 注解的示例:

@RestController
public class WebSocketController {

    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws Exception {
        Thread.sleep(1000); // simulated delay
        return new Greeting("Hello, " + message.getName() + "!");
    }

}

以上代码中,@MessageMapping("/hello") 注解表示该方法用于处理客户端发送的 /hello 消息。@SendTo("/topic/greetings") 注解表示将返回的消息发送到 /topic/greetings 目的地。

客户端在订阅 /topic/greetings 目的地时,就可以接收到该消息了。示例代码如下:

var socket = new SockJS('/gs-guide-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
    stompClient.subscribe('/topic/greetings', function(greeting){
        showGreeting(JSON.parse(greeting.body).content);
    });
});

以上代码中,stompClient.subscribe('/topic/greetings', function(greeting){...}) 表示订阅 /topic/greetings 目的地,并在收到消息时触发回调函数,将消息显示在页面上。

示例代码

为了更好地理解 @SendTo 注解的使用方法,下面给出一个完整的示例代码。该示例代码实现了一个简单的聊天室功能,用户可以在聊天室中发送消息,其他用户可以收到消息。

首先,我们需要创建一个 WebSocket 配置类,用于配置 WebSocket 的相关参数。代码如下:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

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

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

}

以上代码中,configureMessageBroker 方法用于配置消息代理,registerStompEndpoints 方法用于注册 WebSocket 端点。enableSimpleBroker("/topic") 表示启用简单的消息代理,并将消息发送到 /topic 目的地。setApplicationDestinationPrefixes("/app") 表示设置应用程序前缀为 /appaddEndpoint("/chat").withSockJS() 表示注册一个 WebSocket 端点,并启用 SockJS 支持。

接下来,我们需要创建一个 WebSocket 控制器类,用于处理客户端发送的消息。代码如下:

@RestController
public class WebSocketController {

    private final SimpMessagingTemplate messagingTemplate;

    public WebSocketController(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    @MessageMapping("/chat.sendMessage")
    @SendTo("/topic/public")
    public ChatMessage sendMessage(@Payload ChatMessage chatMessage) {
        return chatMessage;
    }

    @MessageMapping("/chat.addUser")
    @SendTo("/topic/public")
    public ChatMessage addUser(@Payload ChatMessage chatMessage,
                               SimpMessageHeaderAccessor headerAccessor) {
        headerAccessor.getSessionAttributes().put("username", chatMessage.getSender());
        return chatMessage;
    }

}

以上代码中,@MessageMapping("/chat.sendMessage") 注解表示该方法用于处理客户端发送的 /chat.sendMessage 消息。@SendTo("/topic/public") 注解表示将返回的消息发送到 /topic/public 目的地。sendMessage 方法用于发送消息。

@MessageMapping("/chat.addUser") 注解表示该方法用于处理客户端发送的 /chat.addUser 消息。addUser 方法用于添加用户。

最后,我们需要创建一个前端页面,用于显示聊天室界面,并处理用户输入的消息。代码如下:

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Chat Example</title>
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
    <script type="text/javascript">
        var stompClient = null;

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

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

        function sendMessage() {
            var sender = $("#sender").val();
            var content = $("#content").val();
            stompClient.send("/app/chat.sendMessage", {}, JSON.stringify({
                sender: sender,
                content: content
            }));
        }

        function addUser() {
            var sender = $("#sender").val();
            stompClient.send("/app/chat.addUser", {}, JSON.stringify({
                sender: sender,
                content: ' has joined the chat'
            }));
        }

        function showMessage(message) {
            $("#chat").append("<tr><td>" + message.sender + ": " + message.content + "</td></tr>");
        }

        $(function () {
            $("form").on('submit', function (e) {
                e.preventDefault();
            });
            connect();
            $("#send").click(function () {
                sendMessage();
                $("#content").val("");
            });
            $("#join").click(function () {
                addUser();
                $("#sender").prop("readonly", true);
                $("#join").prop("disabled", true);
                $("#send").prop("disabled", false);
                $("#content").prop("disabled", false);
            });
        });
    </script>
</head>
<body>
<div>
    <form>
        <label for="sender">Username:</label>
        <input type="text" id="sender" name="sender"/>
        <button type="button" id="join">Join</button>
        <br/>
        <label for="content">Message:</label>
        <input type="text" id="content" name="content"/>
        <button type="button" id="send" disabled="disabled">Send</button>
    </form>
</div>
<div>
    <table id="chat"></table>
</div>
</body>
</html>

以上代码中,connect 方法用于建立 WebSocket 连接。disconnect 方法用于断开 WebSocket 连接。sendMessage 方法用于发送消息。addUser 方法用于添加用户。showMessage 方法用于显示消息。

总结

通过本文的介绍,我们了解了 Spring Boot 中的 @SendTo 注解的原理和使用方法。@SendTo 注解是实现 WebSocket 消息转发功能的关键注解,可以让我们轻松地实现消息的发送和接收。

;