z, ? | toggle help (this) |
space, → | next slide |
shift-space, ← | previous slide |
d | toggle debug mode |
## <ret> | go to slide # |
c, t | table of contents (vi) |
f | toggle footer |
r | reload slides |
n | toggle notes |
p | run preshow |
JSR-356
@ServerEndpoint
per application@RequestMapping
?
SEND
SUBSCRIBE
UNSUBSCRIBE
MESSAGE
ERROR
RECEIPT
ACK
NACK
"Destination"
Header"/queue/a"
, "/topic/a"
)spring-messaging
Message
, MessageChannel
, MesageHandler
, ...)
@Controller
public class GreetingController {
// Receive client messages to destination "/greeting"
@MessageMapping("/greeting")
public void greet(String greeting) {
}
}
@Controller
public class GreetingController {
// Receive client messages to destination "/greeting"
// Process + send to subscribers of "/topic/greetings"
@MessageMapping("/greeting")
@SendTo("/topic/greetings")
public String greet(String greeting) {
return "[" + getTimestamp() + "]: " + greeting;
}
}
"/topic/greetings"
Subscriptions?
@Configuration
@EnableWebSocketMessageBroker
public class Config implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry r) {
r.addEndpoint("/stomp"); // WebSocket URL prefix
}
@Override
public void configureMessageBroker(MessageBrokerConfigurer c) {
c.enableSimpleBroker("/topic/"); // destination prefix
c.setAnnotationMethodDestinationPrefixes("/app");
}
}
@Controller
public class GreetingController {
@Autowired
private SimpMessagingTemplate template;
@RequestMapping(value="/greeting", method=POST)
public void greet(String greeting) {
String text = "[" + getTimeStamp() + "]:" + greeting;
this.template.convertAndSend("/topic/greeting", text);
}
}
@Controller
public class PortfolioController {
@SubscribeEvent("/positions")
public List<PortfolioPosition> getPositions(Principal user) {
Portfolio portfolio = ...
return portfolio.getPositions();
}
}
SUBSCRIBE
, UNSUBSCRIBE
, MESSAGE
)
@Configuration
@EnableWebSocketMessageBroker
public class Config implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerConfigurer c) {
c.enableStompBrokerRelay("/queue/", "/topic/");
c.setAnnotationMethodDestinationPrefixes("/app");
}
// ...
}
CONNECT
frame has authentication headers
@Controller
public class GreetingController {
@MessageMapping("/greeting")
@SendTo("/topic/greetings")
public String greet(String greeting, Principal user) {
return "[" + user + "] says: " + greeting;
}
}
@Controller
public class GreetingController {
// ...
@MessageExceptionHandler
@SendToUser("/queue/errors")
public String handleException(IllegalStateException ex) {
return ex.getMessage();
}
}
@Service
public class TradeService {
@Autowired
private SimpMessagingTemplate template;
public void executeTrade(Trade trade) {
String user = trade.getUser();
String dest = "/queue/position-updates";
TradeResult result = ...
this.template.convertAndSendToUser(user, dest, result);
}
}
@SendToUser("/queue/a")
"/user/{user}/queue/a"
"/queue/a/"
+ unique queue-suffix
CONNECTED
frame provides that suffix"/exchange/amq.direct/a"