====== Basic Websocket ======
This is going to build a STOMP based websocket on server site.
- Add dependency to POM.XML
- Add a EnableWebSocketMessageBroker configuration
- Add a controller to handle the web socket package.
===== Add dependency to POM.XML =====
Add the following in POM.XML
org.springframework.boot
spring-boot-starter-websocket
===== EnableWebSocketMessageBroker =====
Create a java class that @Configuration and @EnableWebSocketMessageBroker. Here we register an endpoint ''/my-websocket-endpoint'' for frontend to connect to. We add the prefix ''/app'' as application destination prefix so that when the client send their request, they need to add it in their destination. And we have add a channel ''topic'' for client to subscribe.
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("/my-websocket-endpoint").withSockJS();
}
}
===== Controller to Send and Receive =====
We user @MessageMapping to get the client request, and @SendToUser to send respond back to the requested client, or @SendTo to respond to all clients that subscribe to the channel. The server can also send package to the client by using SimpMessagingTemplate.
@Controller
public class GreetingController {
private final SimpMessagingTemplate simpMessagingTemplate;
public GreetingController(SimpMessagingTemplate simpMessagingTemplate) {
this.simpMessagingTemplate = simpMessagingTemplate;
}
@MessageMapping("/hello")
@SendToUser("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
Thread.sleep(1000); // simulated delay
return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
}
@MessageMapping("/helloToAll")
@SendTo("/topic/greetings")
public Greeting greetingToAll(HelloMessage message) throws Exception {
Thread.sleep(1000); // simulated delay
return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
}
public void broadcastNews() {
this.simpMessagingTemplate.convertAndSend("/topic/news", new Greeting("This is a news broadcast"));
}
}
===== JavaScript client =====
First import sockjs, and stomp.js library.
==== Connect to server ====
function connect() {
var socket = new SockJS('/my-websocket-endpoint');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/user/topic/greetings', function (greeting) {
console.log(JSON.parse(greeting.body).content);
});
stompClient.subscribe('/topic/greetings', function (greeting) {
console.log(JSON.parse(greeting.body).content);
});
stompClient.subscribe('/topic/news', function (greeting) {
console.log(JSON.parse(greeting.body).content);
});
});
}
==== To Disconnect ====
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
==== To Send ====
We have mapped ''/hello'' to one of our method in the controller. Since we set ''/app'' as prefix, we need to do the following:
stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
==== To Receive ====
We have already setup those callback functions while we subscribe the channels during the connection.
===== Notes =====
* The websocket has a default 25 second keep-a-live package.
* The socket will auto disconnect when the browser/tab is closed.