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
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
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.