Server-side WebSocket API 

WebFlux offers WebSocketHandler as the central interface for handling WebSocket connections. This interface has a method called handle, which accepts WebSocketSession. The WebSocketSession class represents a successful handshake between the client and server and provides access to information, including information about the handshake, session attributes, and the incoming stream of data. In order to learn how to deal with this information, let's consider the following example of responding to the sender with echo messages:

class EchoWebSocketHandler implements WebSocketHandler {           // (1)
@Override //
public Mono<Void> handle(WebSocketSession session) { // (2)
return session // (3)
.receive() // (4)
.map(WebSocketMessage::getPayloadAsText) // (5)
.map(tm -> "Echo: " + tm) // (6)
.map(session::textMessage) // (7)
.as(session::send); // (8)
} //
}

As we can see from the previous example, the new WebSocket API is built on top of the reactive types from Project Reactor. Here, at point (1), we provide an implementation of the WebSocketHandler interface and override the handle method at point (2). Then, we use the WebSocketSession#receive method at point (3) in order to build the processing flow of the incoming WebSocketMessage using the Flux API. WebSocketMessage is a wrapper around DataBuffer and provides additional functionalities, such as translating the payload represented in bytes to text in point (5). Once the incoming message is extracted, we prepend to that text the "Echo: " suffix shown at point (6), wrap the new text message in the WebSocketMessage, and send it back to the client using the WebSocketSession#send method. Here, the send method accepts Publisher<WebSocketMessage> and returns Mono<Void> as the result. Therefore, using the as operator from the Reactor API, we may treat Flux as Mono<Void> and use session::send as a transformation function.

Apart from the WebSocketHandler interface implementation, setting up the server-side WebSocket API requires configuring additional HandlerMapping and WebSocketHandlerAdapter instances. Consider the following code as an example of such a configuration:

@Configuration                                                     // (1)
public class WebSocketConfiguration { //

@Bean // (2)
public HandlerMapping handlerMapping() { //
SimpleUrlHandlerMapping mapping = //
new SimpleUrlHandlerMapping(); // (2.1)
mapping.setUrlMap(Collections.singletonMap( // (2.2)
"/ws/echo", //
new EchoWebSocketHandler() //
)); //
mapping.setOrder(-1); // (2.3)
return mapping; //
} //

@Bean // (3)
public HandlerAdapter handlerAdapter() { //
return new WebSocketHandlerAdapter(); //
} //
}

The preceding example can be described as follows: 

  1. This is the class that is annotated with @Configuration.
  2. Here, we have the declaration and setup of the HandlerMapping bean. At point (2.1), we create SimpleUrlHandlerMapping, which allows setup path-based mapping, shown at point (2.2), to WebSocketHandler. In order to allow SimpleUrlHandlerMapping to be handled prior to other HandlerMapping instances, it should be a higher priority.
  3. This is the declaration of the HandlerAdapter bean, which is WebSocketHandlerAdapter. Here, WebSocketHandlerAdapter plays the most important role, since it upgrades the HTTP connection to the WebSocket one and then calls the WebSocketHandler#handle method.

As we can see, the configuration of the WebSocket API is straightforward.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.85.181