ether-websocket-core define los contratos para WebSockets en Ether: WebSocketEndpoint, WebSocketSession y WebSocketRoute. Independiente del servidor concreto.
Instalación
<dependency>
<groupId>dev.rafex.ether.websocket.core</groupId>
<artifactId>ether-websocket-core</artifactId>
<version>8.0.0-SNAPSHOT</version>
</dependency>
WebSocketEndpoint — implementar un endpoint
public class ChatEndpoint implements WebSocketEndpoint {
private static final EtherLog LOG = EtherLog.getLogger(ChatEndpoint.class);
private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
@Override
public void onOpen(WebSocketSession session) {
sessions.put(session.id(), session);
String room = session.pathParam("room");
LOG.info("Cliente conectado id={} room={}", session.id(), room);
session.sendText("Bienvenido a la sala: " + room);
}
@Override
public void onText(WebSocketSession session, String message) {
LOG.debug("Mensaje de {} : {}", session.id(), message);
String room = session.pathParam("room");
sessions.values().stream()
.filter(s -> room.equals(s.pathParam("room")) && s.isOpen())
.forEach(s -> s.sendText(session.id() + ": " + message));
}
@Override
public void onBinary(WebSocketSession session, ByteBuffer data) {
session.sendBinary(data);
}
@Override
public void onClose(WebSocketSession session, WebSocketCloseStatus status) {
sessions.remove(session.id());
LOG.info("Cliente desconectado id={} code={}", session.id(), status.code());
}
@Override
public void onError(WebSocketSession session, Throwable error) {
LOG.error("Error en session {}: {}", session.id(), error.getMessage());
sessions.remove(session.id());
}
@Override
public Set<String> subprotocols() {
return Set.of("chat");
}
}
WebSocketSession — operaciones en la conexión
String id = session.id();
String path = session.path();
String subprotocol = session.subprotocol();
String room = session.pathParam("room");
String userId = session.queryFirst("userId");
String origin = session.headerFirst("Origin");
boolean open = session.isOpen();
session.attribute("userId", authenticatedUserId);
Long uid = (Long) session.attribute("userId");
CompletionStage<Void> sent = session.sendText("hola");
sent.toCompletableFuture().get();
session.sendBinary(ByteBuffer.wrap(bytes));
session.close(WebSocketCloseStatus.NORMAL_CLOSURE);
WebSocketRoute — asociar patrón de URL a endpoint
WebSocketRoute route1 = WebSocketRoute.of("/chat/{room}", new ChatEndpoint());
WebSocketRoute route2 = WebSocketRoute.of("/notifications", new NotificationsEndpoint());
WebSocketRoute route3 = WebSocketRoute.of("/live/{stream}/data", new StreamEndpoint());
WebSocketCloseStatus — códigos de cierre
WebSocketCloseStatus.NORMAL_CLOSURE
WebSocketCloseStatus.GOING_AWAY
WebSocketCloseStatus.PROTOCOL_ERROR
WebSocketCloseStatus.UNSUPPORTED_DATA
WebSocketCloseStatus.NO_STATUS_RCVD
WebSocketCloseStatus.ABNORMAL_CLOSURE
Más información