Switch to single message method for WebSocketHandler
This commit is contained in:
parent
5f22cf0532
commit
861ab900ae
|
|
@ -57,7 +57,7 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
|
|||
* @param sessionId
|
||||
* @param handlerProvider the recipient of SockJS messages
|
||||
*/
|
||||
public AbstractSockJsSession(String sessionId, HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
public AbstractSockJsSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handlerProvider) {
|
||||
Assert.notNull(sessionId, "sessionId is required");
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
this.sessionId = sessionId;
|
||||
|
|
@ -136,12 +136,12 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
|
|||
|
||||
public void delegateMessages(String[] messages) {
|
||||
for (String message : messages) {
|
||||
this.handler.handleTextMessage(new TextMessage(message), this);
|
||||
this.handler.handleMessage(this, new TextMessage(message));
|
||||
}
|
||||
}
|
||||
|
||||
public void delegateError(Throwable ex) {
|
||||
this.handler.handleTransportError(ex, this);
|
||||
this.handler.handleTransportError(this, ex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -160,7 +160,7 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
|
|||
}
|
||||
finally {
|
||||
this.state = State.CLOSED;
|
||||
this.handler.afterConnectionClosed(status, this);
|
||||
this.handler.afterConnectionClosed(this, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
|
|||
}
|
||||
finally {
|
||||
this.state = State.CLOSED;
|
||||
this.handler.afterConnectionClosed(status, this);
|
||||
this.handler.afterConnectionClosed(this, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,6 @@ public interface SockJsSessionFactory<S extends WebSocketSession>{
|
|||
* @param handler the underlying {@link WebSocketHandler}
|
||||
* @return a new non-null session
|
||||
*/
|
||||
S createSession(String sessionId, HandlerProvider<WebSocketHandler> handler);
|
||||
S createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public abstract class AbstractServerSockJsSession extends AbstractSockJsSession
|
|||
|
||||
|
||||
public AbstractServerSockJsSession(String sessionId, SockJsConfiguration config,
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
|
||||
super(sessionId, handler);
|
||||
this.sockJsConfig = config;
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
|||
* @throws Exception
|
||||
*/
|
||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String sockJsPath, HandlerProvider<WebSocketHandler> handler)
|
||||
String sockJsPath, HandlerProvider<WebSocketHandler<?>> handler)
|
||||
throws IOException, TransportErrorException {
|
||||
|
||||
logger.debug(request.getMethod() + " [" + sockJsPath + "]");
|
||||
|
|
@ -255,10 +255,10 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
|
|||
}
|
||||
|
||||
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler) throws IOException;
|
||||
HandlerProvider<WebSocketHandler<?>> handler) throws IOException;
|
||||
|
||||
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler> handler)
|
||||
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler<?>> handler)
|
||||
throws IOException, TransportErrorException;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,6 @@ import org.springframework.websocket.WebSocketHandler;
|
|||
public interface SockJsService {
|
||||
|
||||
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, String sockJsPath,
|
||||
HandlerProvider<WebSocketHandler> handler) throws IOException, TransportErrorException;
|
||||
HandlerProvider<WebSocketHandler<?>> handler) throws IOException, TransportErrorException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,6 @@ public interface TransportHandler {
|
|||
TransportType getTransportType();
|
||||
|
||||
void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler, AbstractSockJsSession session) throws TransportErrorException;
|
||||
HandlerProvider<WebSocketHandler<?>> handler, AbstractSockJsSession session) throws TransportErrorException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
|||
|
||||
@Override
|
||||
protected void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler) throws IOException {
|
||||
HandlerProvider<WebSocketHandler<?>> handler) throws IOException {
|
||||
|
||||
if (isWebSocketEnabled()) {
|
||||
TransportHandler transportHandler = this.transportHandlers.get(TransportType.WEBSOCKET);
|
||||
|
|
@ -160,7 +160,7 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
|||
|
||||
@Override
|
||||
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler> handler)
|
||||
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler<?>> handler)
|
||||
throws IOException, TransportErrorException {
|
||||
|
||||
TransportHandler transportHandler = this.transportHandlers.get(transportType);
|
||||
|
|
@ -210,7 +210,7 @@ public class DefaultSockJsService extends AbstractSockJsService {
|
|||
transportHandler.handleRequest(request, response, handler, session);
|
||||
}
|
||||
|
||||
public AbstractSockJsSession getSockJsSession(String sessionId, HandlerProvider<WebSocketHandler> handler,
|
||||
public AbstractSockJsSession getSockJsSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler,
|
||||
TransportHandler transportHandler) {
|
||||
|
||||
AbstractSockJsSession session = this.sessions.get(sessionId);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
|
|||
|
||||
private final SockJsService sockJsService;
|
||||
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
private final HandlerProvider<WebSocketHandler<?>> handlerProvider;
|
||||
|
||||
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
|
|||
|
||||
this.prefix = prefix;
|
||||
this.sockJsService = sockJsService;
|
||||
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler>(handler);
|
||||
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler<?>>(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,7 +76,7 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
|
|||
* Servlet container this is the path within the current servlet mapping.
|
||||
*/
|
||||
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService,
|
||||
HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
HandlerProvider<WebSocketHandler<?>> handlerProvider) {
|
||||
|
||||
Assert.hasText(prefix, "prefix is required");
|
||||
Assert.notNull(sockJsService, "sockJsService is required");
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public abstract class AbstractHttpReceivingTransportHandler implements Transport
|
|||
|
||||
@Override
|
||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> webSocketHandler, AbstractSockJsSession session)
|
||||
HandlerProvider<WebSocketHandler<?>> webSocketHandler, AbstractSockJsSession session)
|
||||
throws TransportErrorException {
|
||||
|
||||
if (session == null) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public abstract class AbstractHttpSendingTransportHandler
|
|||
|
||||
@Override
|
||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> webSocketHandler, AbstractSockJsSession session)
|
||||
HandlerProvider<WebSocketHandler<?>> webSocketHandler, AbstractSockJsSession session)
|
||||
throws TransportErrorException {
|
||||
|
||||
// Set content type before writing
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
|
|||
|
||||
|
||||
public AbstractHttpServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
|
||||
super(sessionId, sockJsConfig, handler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public class EventSourceTransportHandler extends AbstractHttpSendingTransportHan
|
|||
}
|
||||
|
||||
@Override
|
||||
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
|
|||
}
|
||||
|
||||
@Override
|
||||
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
|
||||
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
|
|||
}
|
||||
|
||||
@Override
|
||||
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import org.springframework.websocket.WebSocketHandler;
|
|||
public class PollingServerSockJsSession extends AbstractHttpServerSockJsSession {
|
||||
|
||||
public PollingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
|
||||
super(sessionId, sockJsConfig, handler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ import org.springframework.util.StringUtils;
|
|||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.TextWebSocketHandlerAdapter;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
import org.springframework.websocket.adapter.TextWebSocketHandlerAdapter;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
|
|||
|
||||
private final SockJsConfiguration sockJsConfig;
|
||||
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
private final HandlerProvider<WebSocketHandler<?>> handlerProvider;
|
||||
|
||||
private WebSocketServerSockJsSession sockJsSession;
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
|
|||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
|
||||
public SockJsWebSocketHandler(SockJsConfiguration config, HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
public SockJsWebSocketHandler(SockJsConfiguration config, HandlerProvider<WebSocketHandler<?>> handlerProvider) {
|
||||
Assert.notNull(config, "sockJsConfig is required");
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
this.sockJsConfig = config;
|
||||
|
|
@ -74,17 +74,17 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handleTextMessage(TextMessage message, WebSocketSession wsSession) {
|
||||
public void handleMessage(WebSocketSession wsSession, TextMessage message) {
|
||||
this.sockJsSession.handleMessage(message, wsSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(CloseStatus status, WebSocketSession wsSession) {
|
||||
public void afterConnectionClosed(WebSocketSession wsSession, CloseStatus status) {
|
||||
this.sockJsSession.delegateConnectionClosed(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(Throwable exception, WebSocketSession webSocketSession) {
|
||||
public void handleTransportError(WebSocketSession webSocketSession, Throwable exception) {
|
||||
this.sockJsSession.delegateError(exception);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class StreamingServerSockJsSession extends AbstractHttpServerSockJsSessio
|
|||
|
||||
|
||||
public StreamingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
|
||||
super(sessionId, sockJsConfig, handler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
|
|||
|
||||
@Override
|
||||
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler, AbstractSockJsSession session) throws TransportErrorException {
|
||||
HandlerProvider<WebSocketHandler<?>> handler, AbstractSockJsSession session) throws TransportErrorException {
|
||||
|
||||
try {
|
||||
WebSocketHandler sockJsWrapper = new SockJsWebSocketHandler(this.sockJsConfig, handler);
|
||||
this.handshakeHandler.doHandshake(request, response, new SimpleHandlerProvider<WebSocketHandler>(sockJsWrapper));
|
||||
WebSocketHandler<?> sockJsWrapper = new SockJsWebSocketHandler(this.sockJsConfig, handler);
|
||||
this.handshakeHandler.doHandshake(request, response, new SimpleHandlerProvider<WebSocketHandler<?>>(sockJsWrapper));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new TransportErrorException("Failed to start handshake request", t, session.getId());
|
||||
|
|
@ -80,7 +80,7 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
|
|||
|
||||
@Override
|
||||
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler) throws IOException {
|
||||
HandlerProvider<WebSocketHandler<?>> handler) throws IOException {
|
||||
|
||||
return this.handshakeHandler.doHandshake(request, response, handler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHand
|
|||
return new DefaultFrameFormat("%s\n");
|
||||
}
|
||||
|
||||
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHa
|
|||
}
|
||||
|
||||
@Override
|
||||
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
|
||||
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link WebSocketMessage} that contains a binary {@link ByteBuffer} payload.
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author rossen
|
||||
*/
|
||||
public class BinaryWebSocketHandlerAdapter extends WebSocketHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void handleTextMessage(TextMessage message, WebSocketSession session) {
|
||||
try {
|
||||
session.close(CloseStatus.NOT_ACCEPTABLE.withReason("Text messages not supported"));
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class TextWebSocketHandlerAdapter extends WebSocketHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void handleBinaryMessage(BinaryMessage message, WebSocketSession session) {
|
||||
try {
|
||||
session.close(CloseStatus.NOT_ACCEPTABLE.withReason("Binary messages not supported"));
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,10 +19,14 @@ package org.springframework.websocket;
|
|||
/**
|
||||
* A handler for WebSocket sessions.
|
||||
*
|
||||
* @param <T> The type of message being handled {@link TextMessage}, {@link BinaryMessage}
|
||||
* (or {@link WebSocketMessage} for both).
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Phillip Webb
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface WebSocketHandler {
|
||||
public interface WebSocketHandler<T extends WebSocketMessage<?>> {
|
||||
|
||||
/**
|
||||
* A new WebSocket connection has been opened and is ready to be used.
|
||||
|
|
@ -30,23 +34,18 @@ public interface WebSocketHandler {
|
|||
void afterConnectionEstablished(WebSocketSession session);
|
||||
|
||||
/**
|
||||
* Handle an incoming text message.
|
||||
* Handle an incoming WebSocket message.
|
||||
*/
|
||||
void handleTextMessage(TextMessage message, WebSocketSession session);
|
||||
void handleMessage(WebSocketSession session, T message);
|
||||
|
||||
/**
|
||||
* Handle an incoming binary message.
|
||||
* Handle an error from the underlying WebSocket message transport.
|
||||
*/
|
||||
void handleBinaryMessage(BinaryMessage message, WebSocketSession session);
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
void handleTransportError(Throwable exception, WebSocketSession session);
|
||||
void handleTransportError(WebSocketSession session, Throwable exception);
|
||||
|
||||
/**
|
||||
* A WebSocket connection has been closed.
|
||||
*/
|
||||
void afterConnectionClosed(CloseStatus closeStatus, WebSocketSession session);
|
||||
void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A message that can be sent or received over a WebSocket connection. A WebSocket
|
||||
* message must be either a {@link BinaryMessage} or a {@link TextMessage} depending
|
||||
* on the payload. No further subclasses are supported.
|
||||
* A message that can be handled or sent during a WebSocket interaction. There are only
|
||||
* two sub-classes {@link BinaryMessage} or a {@link TextMessage} with no further
|
||||
* sub-classing expected.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
|
|
@ -35,7 +35,7 @@ public abstract class WebSocketMessage<T> {
|
|||
|
||||
|
||||
/**
|
||||
* Create a new {@link WebSocketMessage} instance.
|
||||
* Create a new {@link WebSocketMessage} instance with the given payload.
|
||||
* @param payload a non-null payload
|
||||
*/
|
||||
WebSocketMessage(T payload) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.websocket.adapter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.BinaryMessage;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketMessage;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
|
||||
/**
|
||||
* An base class for implementations adapting {@link WebSocketSession}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public abstract class AbstractWebSocketSesssionAdapter implements WebSocketSession {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
|
||||
@Override
|
||||
public final void sendMessage(WebSocketMessage message) throws IOException {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Sending " + message + ", " + this);
|
||||
}
|
||||
Assert.isTrue(isOpen(), "Cannot send message after connection closed.");
|
||||
if (message instanceof TextMessage) {
|
||||
sendTextMessage((TextMessage) message);
|
||||
}
|
||||
else if (message instanceof BinaryMessage) {
|
||||
sendBinaryMessage((BinaryMessage) message);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unexpected WebSocketMessage type: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void sendTextMessage(TextMessage message) throws IOException ;
|
||||
|
||||
protected abstract void sendBinaryMessage(BinaryMessage message) throws IOException ;
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
close(CloseStatus.NORMAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void close(CloseStatus status) throws IOException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Closing " + this);
|
||||
}
|
||||
closeInternal(status);
|
||||
}
|
||||
|
||||
protected abstract void closeInternal(CloseStatus status) throws IOException;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WebSocket session id=" + getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.websocket.adapter;
|
||||
|
||||
import org.springframework.websocket.BinaryMessage;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link WebSocketHandler} for binary messages with empty methods.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Phillip Webb
|
||||
* @since 4.0
|
||||
*/
|
||||
public class BinaryWebSocketHandlerAdapter implements WebSocketHandler<BinaryMessage> {
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(WebSocketSession session, BinaryMessage message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ import org.springframework.websocket.CloseStatus;
|
|||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketMessage;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
/**
|
||||
|
|
@ -38,12 +39,12 @@ public class JettyWebSocketListenerAdapter implements WebSocketListener {
|
|||
|
||||
private static Log logger = LogFactory.getLog(JettyWebSocketListenerAdapter.class);
|
||||
|
||||
private final WebSocketHandler handler;
|
||||
private final WebSocketHandler<WebSocketMessage<?>> handler;
|
||||
|
||||
private WebSocketSession wsSession;
|
||||
|
||||
|
||||
public JettyWebSocketListenerAdapter(HandlerProvider<WebSocketHandler> provider) {
|
||||
public JettyWebSocketListenerAdapter(HandlerProvider<WebSocketHandler<?>> provider) {
|
||||
Assert.notNull(provider, "provider is required");
|
||||
this.handler = new WebSocketHandlerInvoker(provider).setLogger(logger);
|
||||
}
|
||||
|
|
@ -58,23 +59,23 @@ public class JettyWebSocketListenerAdapter implements WebSocketListener {
|
|||
@Override
|
||||
public void onWebSocketClose(int statusCode, String reason) {
|
||||
CloseStatus closeStatus = new CloseStatus(statusCode, reason);
|
||||
this.handler.afterConnectionClosed(closeStatus, this.wsSession);
|
||||
this.handler.afterConnectionClosed(this.wsSession, closeStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketText(String payload) {
|
||||
TextMessage message = new TextMessage(payload);
|
||||
this.handler.handleTextMessage(message, this.wsSession);
|
||||
this.handler.handleMessage(this.wsSession, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketBinary(byte[] payload, int offset, int len) {
|
||||
BinaryMessage message = new BinaryMessage(payload, offset, len);
|
||||
this.handler.handleBinaryMessage(message, this.wsSession);
|
||||
this.handler.handleMessage(this.wsSession, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebSocketError(Throwable cause) {
|
||||
this.handler.handleTransportError(cause, this.wsSession);
|
||||
this.handler.handleTransportError(this.wsSession, cause);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import org.springframework.util.ObjectUtils;
|
|||
import org.springframework.websocket.BinaryMessage;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketMessage;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
|
||||
|
|
@ -34,7 +33,7 @@ import org.springframework.websocket.WebSocketSession;
|
|||
* @author Phillip Webb
|
||||
* @since 4.0
|
||||
*/
|
||||
public class JettyWebSocketSessionAdapter implements WebSocketSession {
|
||||
public class JettyWebSocketSessionAdapter extends AbstractWebSocketSesssionAdapter {
|
||||
|
||||
private Session session;
|
||||
|
||||
|
|
@ -65,33 +64,17 @@ public class JettyWebSocketSessionAdapter implements WebSocketSession {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(WebSocketMessage message) throws IOException {
|
||||
if (message instanceof BinaryMessage) {
|
||||
sendMessage((BinaryMessage) message);
|
||||
}
|
||||
else if (message instanceof TextMessage) {
|
||||
sendMessage((TextMessage) message);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unsupported message type");
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(BinaryMessage message) throws IOException {
|
||||
this.session.getRemote().sendBytes(message.getPayload());
|
||||
}
|
||||
|
||||
private void sendMessage(TextMessage message) throws IOException {
|
||||
protected void sendTextMessage(TextMessage message) throws IOException {
|
||||
this.session.getRemote().sendString(message.getPayload());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.session.close();
|
||||
protected void sendBinaryMessage(BinaryMessage message) throws IOException {
|
||||
this.session.getRemote().sendBytes(message.getPayload());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(CloseStatus status) throws IOException {
|
||||
protected void closeInternal(CloseStatus status) throws IOException {
|
||||
this.session.close(status.getCode(), status.getReason());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import org.springframework.websocket.HandlerProvider;
|
|||
import org.springframework.websocket.PartialMessageHandler;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketMessage;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
|
||||
|
|
@ -45,7 +46,7 @@ public class StandardEndpointAdapter extends Endpoint {
|
|||
|
||||
private static Log logger = LogFactory.getLog(StandardEndpointAdapter.class);
|
||||
|
||||
private final WebSocketHandler handler;
|
||||
private final WebSocketHandler<WebSocketMessage<?>> handler;
|
||||
|
||||
private final Class<?> handlerClass;
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ public class StandardEndpointAdapter extends Endpoint {
|
|||
|
||||
|
||||
|
||||
public StandardEndpointAdapter(HandlerProvider<WebSocketHandler> provider) {
|
||||
public StandardEndpointAdapter(HandlerProvider<WebSocketHandler<?>> provider) {
|
||||
Assert.notNull(provider, "provider is required");
|
||||
this.handler = new WebSocketHandlerInvoker(provider).setLogger(logger);
|
||||
this.handlerClass= provider.getHandlerType();
|
||||
|
|
@ -69,15 +70,8 @@ public class StandardEndpointAdapter extends Endpoint {
|
|||
handleTextMessage(session, message);
|
||||
}
|
||||
});
|
||||
if (PartialMessageHandler.class.isAssignableFrom(this.handlerClass)) {
|
||||
session.addMessageHandler(new MessageHandler.Partial<ByteBuffer>() {
|
||||
@Override
|
||||
public void onMessage(ByteBuffer messagePart, boolean isLast) {
|
||||
handleBinaryMessage(session, messagePart, isLast);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
||||
if (!PartialMessageHandler.class.isAssignableFrom(this.handlerClass)) {
|
||||
session.addMessageHandler(new MessageHandler.Whole<ByteBuffer>() {
|
||||
@Override
|
||||
public void onMessage(ByteBuffer message) {
|
||||
|
|
@ -85,30 +79,38 @@ public class StandardEndpointAdapter extends Endpoint {
|
|||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
session.addMessageHandler(new MessageHandler.Partial<ByteBuffer>() {
|
||||
@Override
|
||||
public void onMessage(ByteBuffer messagePart, boolean isLast) {
|
||||
handleBinaryMessage(session, messagePart, isLast);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.wsSession = new StandardWebSocketSessionAdapter(session);
|
||||
this.handler.afterConnectionEstablished(this.wsSession);
|
||||
}
|
||||
|
||||
private void handleTextMessage(javax.websocket.Session session, String payload) {
|
||||
TextMessage message = new TextMessage(payload);
|
||||
this.handler.handleTextMessage(message, this.wsSession);
|
||||
TextMessage textMessage = new TextMessage(payload);
|
||||
this.handler.handleMessage(this.wsSession, textMessage);
|
||||
}
|
||||
|
||||
private void handleBinaryMessage(javax.websocket.Session session, ByteBuffer payload, boolean isLast) {
|
||||
BinaryMessage message = new BinaryMessage(payload, isLast);
|
||||
this.handler.handleBinaryMessage(message, this.wsSession);
|
||||
BinaryMessage binaryMessage = new BinaryMessage(payload, isLast);
|
||||
this.handler.handleMessage(this.wsSession, binaryMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(javax.websocket.Session session, CloseReason reason) {
|
||||
CloseStatus closeStatus = new CloseStatus(reason.getCloseCode().getCode(), reason.getReasonPhrase());
|
||||
this.handler.afterConnectionClosed(closeStatus, this.wsSession);
|
||||
this.handler.afterConnectionClosed(this.wsSession, closeStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(javax.websocket.Session session, Throwable exception) {
|
||||
this.handler.handleTransportError(exception, this.wsSession);
|
||||
this.handler.handleTransportError(this.wsSession, exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,15 +21,11 @@ import java.net.URI;
|
|||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.CloseReason.CloseCodes;
|
||||
import javax.websocket.RemoteEndpoint.Basic;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.BinaryMessage;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketMessage;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
/**
|
||||
|
|
@ -39,9 +35,7 @@ import org.springframework.websocket.WebSocketSession;
|
|||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class StandardWebSocketSessionAdapter implements WebSocketSession {
|
||||
|
||||
private static Log logger = LogFactory.getLog(StandardWebSocketSessionAdapter.class);
|
||||
public class StandardWebSocketSessionAdapter extends AbstractWebSocketSesssionAdapter {
|
||||
|
||||
private final javax.websocket.Session session;
|
||||
|
||||
|
|
@ -73,39 +67,18 @@ public class StandardWebSocketSessionAdapter implements WebSocketSession {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(WebSocketMessage message) throws IOException {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Sending: " + message + ", " + this);
|
||||
}
|
||||
Assert.isTrue(isOpen(), "Cannot send message after connection closed.");
|
||||
Basic remote = this.session.getBasicRemote();
|
||||
if (message instanceof TextMessage) {
|
||||
remote.sendText(((TextMessage) message).getPayload());
|
||||
}
|
||||
else if (message instanceof BinaryMessage) {
|
||||
remote.sendBinary(((BinaryMessage) message).getPayload());
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unexpected WebSocketMessage type: " + message);
|
||||
}
|
||||
protected void sendTextMessage(TextMessage message) throws IOException {
|
||||
this.session.getBasicRemote().sendText(message.getPayload());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
close(CloseStatus.NORMAL);
|
||||
protected void sendBinaryMessage(BinaryMessage message) throws IOException {
|
||||
this.session.getBasicRemote().sendBinary(message.getPayload());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(CloseStatus status) throws IOException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Closing " + this);
|
||||
}
|
||||
protected void closeInternal(CloseStatus status) throws IOException {
|
||||
this.session.close(new CloseReason(CloseCodes.getCloseCode(status.getCode()), status.getReason()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WebSocket session id=" + getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,36 +14,37 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.websocket;
|
||||
package org.springframework.websocket.adapter;
|
||||
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link WebSocketHandler} with empty methods.
|
||||
* A {@link WebSocketHandler} for text messages with empty methods.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Phillip Webb
|
||||
* @since 4.0
|
||||
* @see WebSocketHandler
|
||||
*/
|
||||
public class WebSocketHandlerAdapter implements WebSocketHandler {
|
||||
public class TextWebSocketHandlerAdapter implements WebSocketHandler<TextMessage> {
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(CloseStatus status, WebSocketSession session) {
|
||||
public void handleMessage(WebSocketSession session, TextMessage message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTextMessage(TextMessage message, WebSocketSession session) {
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBinaryMessage(BinaryMessage message, WebSocketSession session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(Throwable exception, WebSocketSession session) {
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.websocket.adapter;
|
||||
|
||||
import org.springframework.websocket.BinaryMessage;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketMessage;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link WebSocketHandler} for both text and binary messages with empty methods.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Phillip Webb
|
||||
* @since 4.0
|
||||
*
|
||||
* @see TextWebSocketHandlerAdapter
|
||||
* @see BinaryWebSocketHandlerAdapter
|
||||
*/
|
||||
public class WebSocketHandlerAdapter implements WebSocketHandler<WebSocketMessage<?>> {
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
|
||||
if (message instanceof TextMessage) {
|
||||
handleTextMessage(session, (TextMessage) message);
|
||||
}
|
||||
else if (message instanceof BinaryMessage) {
|
||||
handleBinaryMessage(session, (BinaryMessage) message);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unexpected WebSocket message type: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
|
||||
}
|
||||
|
||||
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,36 +20,39 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.BinaryMessage;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketMessage;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
/**
|
||||
* A class for managing and delegating to a {@link WebSocketHandler} instance, applying
|
||||
* initialization and destruction as necessary at the start and end of the WebSocket
|
||||
* session, ensuring that any unhandled exceptions from its methods are caught and handled
|
||||
* by closing the session, and also adding uniform logging.
|
||||
* A class for managing and delegating to a {@link WebSocketHandler} instance, ensuring
|
||||
* the handler is initialized and destroyed, that any unhandled exceptions from handler
|
||||
* are caught (and handled by closing the session), as well as adding logging.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Phillip Webb
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WebSocketHandlerInvoker implements WebSocketHandler {
|
||||
public class WebSocketHandlerInvoker implements WebSocketHandler<WebSocketMessage<?>> {
|
||||
|
||||
private Log logger = LogFactory.getLog(WebSocketHandlerInvoker.class);
|
||||
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
private final HandlerProvider<WebSocketHandler<?>> handlerProvider;
|
||||
|
||||
private WebSocketHandler handler;
|
||||
private final Class<?> supportedMessageType;
|
||||
|
||||
private WebSocketHandler<?> handler;
|
||||
|
||||
private final AtomicInteger sessionCount = new AtomicInteger(0);
|
||||
|
||||
|
||||
public WebSocketHandlerInvoker(HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
this.handlerProvider = handlerProvider;
|
||||
public WebSocketHandlerInvoker(HandlerProvider<WebSocketHandler<?>> provider) {
|
||||
this.handlerProvider = provider;
|
||||
this.supportedMessageType = GenericTypeResolver.resolveTypeArgument(provider.getHandlerType(), WebSocketHandler.class);
|
||||
}
|
||||
|
||||
public WebSocketHandlerInvoker setLogger(Log logger) {
|
||||
|
|
@ -77,8 +80,10 @@ public class WebSocketHandlerInvoker implements WebSocketHandler {
|
|||
tryCloseWithError(session, ex, null);
|
||||
}
|
||||
|
||||
public void tryCloseWithError(WebSocketSession session, Throwable ex, CloseStatus status) {
|
||||
logger.error("Unhandled error for " + session, ex);
|
||||
public void tryCloseWithError(WebSocketSession session, Throwable exeption, CloseStatus status) {
|
||||
if (exeption != null) {
|
||||
logger.error("Closing due to exception for " + session, exeption);
|
||||
}
|
||||
if (session.isOpen()) {
|
||||
try {
|
||||
session.close(CloseStatus.SERVER_ERROR);
|
||||
|
|
@ -103,13 +108,18 @@ public class WebSocketHandlerInvoker implements WebSocketHandler {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handleTextMessage(TextMessage message, WebSocketSession session) {
|
||||
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Received text message for " + session + ": " + message);
|
||||
logger.trace("Received " + message + ", " + session);
|
||||
}
|
||||
if (!this.supportedMessageType.isAssignableFrom(message.getClass())) {
|
||||
tryCloseWithError(session, null, CloseStatus.NOT_ACCEPTABLE.withReason("Message type not supported"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.handler.handleTextMessage(message, session);
|
||||
((WebSocketHandler) this.handler).handleMessage(session, message);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
tryCloseWithError(session,ex);
|
||||
|
|
@ -117,25 +127,12 @@ public class WebSocketHandlerInvoker implements WebSocketHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handleBinaryMessage(BinaryMessage message, WebSocketSession session) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Received binary message for " + session);
|
||||
}
|
||||
try {
|
||||
this.handler.handleBinaryMessage(message, session);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
tryCloseWithError(session, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(Throwable exception, WebSocketSession session) {
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Transport error for " + session, exception);
|
||||
}
|
||||
try {
|
||||
this.handler.handleTransportError(exception, session);
|
||||
this.handler.handleTransportError(session, exception);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
tryCloseWithError(session, ex);
|
||||
|
|
@ -143,12 +140,12 @@ public class WebSocketHandlerInvoker implements WebSocketHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(CloseStatus closeStatus, WebSocketSession session) {
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Connection closed for " + session + ", " + closeStatus);
|
||||
}
|
||||
try {
|
||||
this.handler.afterConnectionClosed(closeStatus, session);
|
||||
this.handler.afterConnectionClosed(session, closeStatus);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.error("Unhandled error for " + this, ex);
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Adapters for the {@link org.springframework.websocket.WebSocketHandler} and
|
||||
* {@link org.springframework.websocket.WebSocketSession} contracts.
|
||||
* Classes adapting Spring's WebSocket API classes to and from various WebSocket
|
||||
* implementations. Also contains convenient base classes for
|
||||
* {@link org.springframework.websocket.WebSocketHandler} implementations.
|
||||
*/
|
||||
package org.springframework.websocket.adapter;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ public interface WebSocketClient {
|
|||
WebSocketSession doHandshake(WebSocketHandler handler,
|
||||
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException;
|
||||
|
||||
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler,
|
||||
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler,
|
||||
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException;
|
||||
|
||||
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler, HttpHeaders headers, URI uri)
|
||||
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler, HttpHeaders headers, URI uri)
|
||||
throws WebSocketConnectFailureException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
|
|||
|
||||
private final WebSocketClient client;
|
||||
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
private final HandlerProvider<WebSocketHandler<?>> handlerProvider;
|
||||
|
||||
private WebSocketSession webSocketSession;
|
||||
|
||||
|
|
@ -46,11 +46,11 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
|
|||
|
||||
super(uriTemplate, uriVariables);
|
||||
this.client = webSocketClient;
|
||||
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler>(webSocketHandler);
|
||||
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler<?>>(webSocketHandler);
|
||||
}
|
||||
|
||||
public WebSocketConnectionManager(WebSocketClient webSocketClient,
|
||||
HandlerProvider<WebSocketHandler> handlerProvider, String uriTemplate, Object... uriVariables) {
|
||||
HandlerProvider<WebSocketHandler<?>> handlerProvider, String uriTemplate, Object... uriVariables) {
|
||||
|
||||
super(uriTemplate, uriVariables);
|
||||
this.client = webSocketClient;
|
||||
|
|
|
|||
|
|
@ -64,10 +64,10 @@ public class StandardWebSocketClient implements WebSocketClient {
|
|||
public WebSocketSession doHandshake(WebSocketHandler handler, String uriTemplate, Object... uriVariables)
|
||||
throws WebSocketConnectFailureException {
|
||||
|
||||
return doHandshake(new SimpleHandlerProvider<WebSocketHandler>(handler), uriTemplate, uriVariables);
|
||||
return doHandshake(new SimpleHandlerProvider<WebSocketHandler<?>>(handler), uriTemplate, uriVariables);
|
||||
}
|
||||
|
||||
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler,
|
||||
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler,
|
||||
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(uriVariables).encode().toUri();
|
||||
|
|
@ -75,7 +75,7 @@ public class StandardWebSocketClient implements WebSocketClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler,
|
||||
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler,
|
||||
final HttpHeaders httpHeaders, URI uri) throws WebSocketConnectFailureException {
|
||||
|
||||
Endpoint endpoint = new StandardEndpointAdapter(handler);
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
|
|||
|
||||
@Override
|
||||
public final boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler) throws IOException {
|
||||
HandlerProvider<WebSocketHandler<?>> handler) throws IOException {
|
||||
|
||||
logger.debug("Starting handshake for " + request.getURI());
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,6 @@ public interface HandshakeHandler {
|
|||
|
||||
|
||||
boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler) throws IOException;
|
||||
HandlerProvider<WebSocketHandler<?>> handler) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public interface RequestUpgradeStrategy {
|
|||
* @param handler the handler for WebSocket messages
|
||||
*/
|
||||
void upgrade(ServerHttpRequest request, ServerHttpResponse response, String selectedProtocol,
|
||||
HandlerProvider<WebSocketHandler> handlerProvider) throws IOException;
|
||||
HandlerProvider<WebSocketHandler<?>> handlerProvider) throws IOException;
|
||||
// FIXME how to indicate failure to upgrade?
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,13 +43,9 @@ public abstract class AbstractEndpointUpgradeStrategy implements RequestUpgradeS
|
|||
|
||||
@Override
|
||||
public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String protocol, HandlerProvider<WebSocketHandler> handler) throws IOException {
|
||||
String protocol, HandlerProvider<WebSocketHandler<?>> handler) throws IOException {
|
||||
|
||||
upgradeInternal(request, response, protocol, adaptWebSocketHandler(handler));
|
||||
}
|
||||
|
||||
protected Endpoint adaptWebSocketHandler(HandlerProvider<WebSocketHandler> handler) {
|
||||
return new StandardEndpointAdapter(handler);
|
||||
upgradeInternal(request, response, protocol, new StandardEndpointAdapter(handler));
|
||||
}
|
||||
|
||||
protected abstract void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
|||
public Object createWebSocket(UpgradeRequest request, UpgradeResponse response) {
|
||||
Assert.isInstanceOf(ServletWebSocketRequest.class, request);
|
||||
ServletWebSocketRequest servletRequest = (ServletWebSocketRequest) request;
|
||||
HandlerProvider<WebSocketHandler> handlerProvider =
|
||||
(HandlerProvider<WebSocketHandler>) servletRequest.getServletAttributes().get(
|
||||
HandlerProvider<WebSocketHandler<?>> handlerProvider =
|
||||
(HandlerProvider<WebSocketHandler<?>>) servletRequest.getServletAttributes().get(
|
||||
HANDLER_PROVIDER_ATTR_NAME);
|
||||
return new JettyWebSocketListenerAdapter(handlerProvider);
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
|||
|
||||
@Override
|
||||
public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String selectedProtocol, HandlerProvider<WebSocketHandler> handlerProvider) throws IOException {
|
||||
String selectedProtocol, HandlerProvider<WebSocketHandler<?>> handlerProvider) throws IOException {
|
||||
|
||||
Assert.isInstanceOf(ServletServerHttpRequest.class, request);
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
|
|
@ -101,7 +101,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
|||
}
|
||||
|
||||
private void upgrade(HttpServletRequest request, HttpServletResponse response,
|
||||
String selectedProtocol, final HandlerProvider<WebSocketHandler> handlerProvider) throws IOException {
|
||||
String selectedProtocol, final HandlerProvider<WebSocketHandler<?>> handlerProvider) throws IOException {
|
||||
|
||||
Assert.state(this.factory.isUpgradeRequest(request, response), "Not a suitable WebSocket upgrade request");
|
||||
Assert.state(this.factory.acceptWebSocket(request, response), "Unable to accept WebSocket");
|
||||
|
|
|
|||
|
|
@ -45,18 +45,18 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler {
|
|||
|
||||
private final HandshakeHandler handshakeHandler;
|
||||
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
private final HandlerProvider<WebSocketHandler<?>> handlerProvider;
|
||||
|
||||
|
||||
public WebSocketHttpRequestHandler(WebSocketHandler webSocketHandler) {
|
||||
this(new SimpleHandlerProvider<WebSocketHandler>(webSocketHandler));
|
||||
this(new SimpleHandlerProvider<WebSocketHandler<?>>(webSocketHandler));
|
||||
}
|
||||
|
||||
public WebSocketHttpRequestHandler( HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
public WebSocketHttpRequestHandler( HandlerProvider<WebSocketHandler<?>> handlerProvider) {
|
||||
this(handlerProvider, new DefaultHandshakeHandler());
|
||||
}
|
||||
|
||||
public WebSocketHttpRequestHandler( HandlerProvider<WebSocketHandler> handlerProvider,
|
||||
public WebSocketHttpRequestHandler( HandlerProvider<WebSocketHandler<?>> handlerProvider,
|
||||
HandshakeHandler handshakeHandler) {
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
Assert.notNull(handshakeHandler, "handshakeHandler is required");
|
||||
|
|
|
|||
Loading…
Reference in New Issue