Add the sse-websocket module
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package com.ankurm.ssews;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.time.Instant;
|
||||
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.messaging.handler.annotation.SendTo;
|
||||
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
|
||||
import org.springframework.messaging.simp.SimpMessageType;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
/**
|
||||
* The chat. Three handlers, each demonstrating a different routing rule.
|
||||
*
|
||||
* @see <a href="../../../../../docs/04-stomp.md">docs/04-stomp.md</a>
|
||||
*/
|
||||
@Controller
|
||||
public class ChatController {
|
||||
|
||||
private final SimpMessagingTemplate template;
|
||||
|
||||
ChatController(SimpMessagingTemplate template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
/** Explicit fan-out destination. Client SENDs to /app/chat.send, subscribers get /topic/room. */
|
||||
@MessageMapping("/chat.send")
|
||||
@SendTo("/topic/room")
|
||||
public ChatMessage send(@Payload ChatMessage in, SimpMessageHeaderAccessor headers) {
|
||||
String from = in.from() == null ? headers.getSessionId() : in.from();
|
||||
return new ChatMessage(from, in.text(), Instant.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* No {@code @SendTo}. The return value still goes somewhere: the default destination is the
|
||||
* broker prefix plus the mapping, i.e. {@code /topic/chat.echo}. That default is why a
|
||||
* handler you thought was private is readable by anyone who guesses the path.
|
||||
*/
|
||||
@MessageMapping("/chat.echo")
|
||||
public ChatMessage echo(@Payload ChatMessage in) {
|
||||
return new ChatMessage("echo", in.text(), Instant.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Point-to-point. Sent to one session's private destination; every other subscriber to
|
||||
* /user/queue/whisper gets nothing, because the broker rewrote the destination per session.
|
||||
*
|
||||
* <p>The three extra lines are not optional and their absence is silent. With no
|
||||
* authenticated {@link Principal} the "user" is the STOMP session id, and
|
||||
* {@code DefaultUserDestinationResolver} can only turn a session id into a real destination
|
||||
* if the message also <em>carries</em> that session id in its headers. Call the two-argument
|
||||
* {@code convertAndSendToUser(sessionId, dest, payload)} instead and the message is resolved
|
||||
* against a user registry that has never heard of that name: no exception, no log line, no
|
||||
* delivery. {@code setLeaveMutable(true)} is required too — without it the accessor is
|
||||
* immutable by the time the resolver looks, and the session id is lost again.
|
||||
*/
|
||||
@MessageMapping("/chat.whisper")
|
||||
public void whisper(@Payload ChatMessage in, SimpMessageHeaderAccessor headers, Principal principal) {
|
||||
String targetSessionId = in.from();
|
||||
SimpMessageHeaderAccessor out = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
|
||||
out.setSessionId(targetSessionId);
|
||||
out.setLeaveMutable(true);
|
||||
template.convertAndSendToUser(targetSessionId, "/queue/whisper",
|
||||
new ChatMessage(principal == null ? headers.getSessionId() : principal.getName(),
|
||||
in.text(), Instant.now()),
|
||||
out.getMessageHeaders());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user