Add HandlerProvider interface
HandlerProvider is now an interface that can be used to plug in WebSocket handlers with per-connection scope semantics. There are two implementations, of the interface, one simple and a second that creates handler instances through AutowireCapableBeanFactory. HandlerProvider also provides a destroy method that is used to apply a destroy callback whenever a client connection closes.
This commit is contained in:
@@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.TextMessageHandler;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
@@ -40,6 +41,8 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
|
||||
|
||||
private final String sessionId;
|
||||
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
|
||||
private final TextMessageHandler handler;
|
||||
|
||||
private State state = State.NEW;
|
||||
@@ -52,14 +55,17 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
|
||||
/**
|
||||
*
|
||||
* @param sessionId
|
||||
* @param handler the recipient of SockJS messages
|
||||
* @param handlerProvider the recipient of SockJS messages
|
||||
*/
|
||||
public AbstractSockJsSession(String sessionId, WebSocketHandler webSocketHandler) {
|
||||
public AbstractSockJsSession(String sessionId, HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
Assert.notNull(sessionId, "sessionId is required");
|
||||
Assert.notNull(webSocketHandler, "webSocketHandler is required");
|
||||
Assert.isInstanceOf(TextMessageHandler.class, webSocketHandler, "Expected a TextMessageHandler");
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
this.sessionId = sessionId;
|
||||
|
||||
WebSocketHandler webSocketHandler = handlerProvider.getHandler();
|
||||
Assert.isInstanceOf(TextMessageHandler.class, webSocketHandler, "Expected a TextMessageHandler");
|
||||
this.handler = (TextMessageHandler) webSocketHandler;
|
||||
this.handlerProvider = handlerProvider;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
@@ -180,7 +186,12 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
|
||||
}
|
||||
finally {
|
||||
this.state = State.CLOSED;
|
||||
this.handler.afterConnectionClosed(status, this);
|
||||
try {
|
||||
this.handler.afterConnectionClosed(status, this);
|
||||
}
|
||||
finally {
|
||||
this.handlerProvider.destroy(this.handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.sockjs;
|
||||
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
@@ -28,6 +29,6 @@ import org.springframework.websocket.WebSocketSession;
|
||||
*/
|
||||
public interface SockJsSessionFactory<S extends WebSocketSession>{
|
||||
|
||||
S createSession(String sessionId, WebSocketHandler webSocketHandler);
|
||||
S createSession(String sessionId, HandlerProvider<WebSocketHandler> handler);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import org.springframework.sockjs.AbstractSockJsSession;
|
||||
import org.springframework.util.Assert;
|
||||
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;
|
||||
@@ -45,9 +46,9 @@ public abstract class AbstractServerSockJsSession extends AbstractSockJsSession
|
||||
|
||||
|
||||
public AbstractServerSockJsSession(String sessionId, SockJsConfiguration config,
|
||||
WebSocketHandler webSocketHandler) {
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
|
||||
super(sessionId, webSocketHandler);
|
||||
super(sessionId, handler);
|
||||
this.sockJsConfig = config;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -218,7 +219,7 @@ public abstract class AbstractSockJsService
|
||||
* @throws Exception
|
||||
*/
|
||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String sockJsPath, WebSocketHandler webSocketHandler) throws Exception {
|
||||
String sockJsPath, HandlerProvider<WebSocketHandler> handler) throws Exception {
|
||||
|
||||
logger.debug(request.getMethod() + " [" + sockJsPath + "]");
|
||||
|
||||
@@ -244,7 +245,7 @@ public abstract class AbstractSockJsService
|
||||
return;
|
||||
}
|
||||
else if (sockJsPath.equals("/websocket")) {
|
||||
handleRawWebSocketRequest(request, response, webSocketHandler);
|
||||
handleRawWebSocketRequest(request, response, handler);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -264,7 +265,7 @@ public abstract class AbstractSockJsService
|
||||
return;
|
||||
}
|
||||
|
||||
handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), webSocketHandler);
|
||||
handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), handler);
|
||||
}
|
||||
finally {
|
||||
response.flush();
|
||||
@@ -272,10 +273,10 @@ public abstract class AbstractSockJsService
|
||||
}
|
||||
|
||||
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler) throws Exception;
|
||||
HandlerProvider<WebSocketHandler> handler) throws Exception;
|
||||
|
||||
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String sessionId, TransportType transportType, WebSocketHandler webSocketHandler) throws Exception;
|
||||
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler> handler) throws Exception;
|
||||
|
||||
|
||||
protected boolean validateRequest(String serverId, String sessionId, String transport) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.sockjs.server;
|
||||
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -30,6 +31,6 @@ public interface SockJsService {
|
||||
|
||||
|
||||
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, String sockJsPath,
|
||||
WebSocketHandler webSocketHandler) throws Exception;
|
||||
HandlerProvider<WebSocketHandler> handler) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.sockjs.server;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.sockjs.AbstractSockJsSession;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -31,6 +32,6 @@ public interface TransportHandler {
|
||||
TransportType getTransportType();
|
||||
|
||||
void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception;
|
||||
HandlerProvider<WebSocketHandler> handler, AbstractSockJsSession session) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.http.Cookie;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -43,6 +42,7 @@ import org.springframework.sockjs.server.transport.XhrPollingTransportHandler;
|
||||
import org.springframework.sockjs.server.transport.XhrStreamingTransportHandler;
|
||||
import org.springframework.sockjs.server.transport.XhrTransportHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.server.DefaultHandshakeHandler;
|
||||
import org.springframework.websocket.server.HandshakeHandler;
|
||||
@@ -54,7 +54,7 @@ import org.springframework.websocket.server.HandshakeHandler;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class DefaultSockJsService extends AbstractSockJsService implements InitializingBean {
|
||||
public class DefaultSockJsService extends AbstractSockJsService {
|
||||
|
||||
private final Map<TransportType, TransportHandler> transportHandlers = new HashMap<TransportType, TransportHandler>();
|
||||
|
||||
@@ -157,13 +157,13 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
|
||||
|
||||
@Override
|
||||
protected void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler) throws Exception {
|
||||
HandlerProvider<WebSocketHandler> handler) throws Exception {
|
||||
|
||||
if (isWebSocketEnabled()) {
|
||||
TransportHandler transportHandler = this.transportHandlers.get(TransportType.WEBSOCKET);
|
||||
if (transportHandler != null) {
|
||||
if (transportHandler instanceof HandshakeHandler) {
|
||||
((HandshakeHandler) transportHandler).doHandshake(request, response, webSocketHandler);
|
||||
((HandshakeHandler) transportHandler).doHandshake(request, response, handler);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
|
||||
|
||||
@Override
|
||||
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String sessionId, TransportType transportType, WebSocketHandler webSocketHandler) throws Exception {
|
||||
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler> handler) throws Exception {
|
||||
|
||||
TransportHandler transportHandler = this.transportHandlers.get(transportType);
|
||||
|
||||
@@ -201,7 +201,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractSockJsSession session = getSockJsSession(sessionId, webSocketHandler, transportHandler);
|
||||
AbstractSockJsSession session = getSockJsSession(sessionId, handler, transportHandler);
|
||||
|
||||
if (session != null) {
|
||||
if (transportType.setsNoCacheHeader()) {
|
||||
@@ -220,10 +220,10 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
|
||||
}
|
||||
}
|
||||
|
||||
transportHandler.handleRequest(request, response, webSocketHandler, session);
|
||||
transportHandler.handleRequest(request, response, handler, session);
|
||||
}
|
||||
|
||||
public AbstractSockJsSession getSockJsSession(String sessionId, WebSocketHandler webSocketHandler,
|
||||
public AbstractSockJsSession getSockJsSession(String sessionId, HandlerProvider<WebSocketHandler> handler,
|
||||
TransportHandler transportHandler) {
|
||||
|
||||
AbstractSockJsSession session = this.sessions.get(sessionId);
|
||||
@@ -240,7 +240,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
|
||||
return session;
|
||||
}
|
||||
logger.debug("Creating new session with session id \"" + sessionId + "\"");
|
||||
session = (AbstractSockJsSession) sessionFactory.createSession(sessionId, webSocketHandler);
|
||||
session = (AbstractSockJsSession) sessionFactory.createSession(sessionId, handler);
|
||||
this.sessions.put(sessionId, session);
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,6 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.http.server.AsyncServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
@@ -36,6 +33,7 @@ import org.springframework.web.util.NestedServletException;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.support.SimpleHandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -43,7 +41,7 @@ import org.springframework.websocket.WebSocketHandler;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactoryAware {
|
||||
public class SockJsHttpRequestHandler implements HttpRequestHandler {
|
||||
|
||||
private final String prefix;
|
||||
|
||||
@@ -61,15 +59,15 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
|
||||
* that begins with the specified prefix will be handled by this service. In a
|
||||
* Servlet container this is the path within the current servlet mapping.
|
||||
*/
|
||||
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebSocketHandler webSocketHandler) {
|
||||
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebSocketHandler handler) {
|
||||
|
||||
Assert.hasText(prefix, "prefix is required");
|
||||
Assert.notNull(sockJsService, "sockJsService is required");
|
||||
Assert.notNull(webSocketHandler, "webSocketHandler is required");
|
||||
Assert.notNull(handler, "webSocketHandler is required");
|
||||
|
||||
this.prefix = prefix;
|
||||
this.sockJsService = sockJsService;
|
||||
this.handlerProvider = new HandlerProvider<WebSocketHandler>(webSocketHandler);
|
||||
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler>(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,15 +78,15 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
|
||||
* Servlet container this is the path within the current servlet mapping.
|
||||
*/
|
||||
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService,
|
||||
Class<? extends WebSocketHandler> webSocketHandlerClass) {
|
||||
HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
|
||||
Assert.hasText(prefix, "prefix is required");
|
||||
Assert.notNull(sockJsService, "sockJsService is required");
|
||||
Assert.notNull(webSocketHandlerClass, "webSocketHandlerClass is required");
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
|
||||
this.prefix = prefix;
|
||||
this.sockJsService = sockJsService;
|
||||
this.handlerProvider = new HandlerProvider<WebSocketHandler>(webSocketHandlerClass);
|
||||
this.handlerProvider = handlerProvider;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
@@ -99,11 +97,6 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
|
||||
return this.prefix + "/**";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.handlerProvider.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
@@ -119,8 +112,7 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
|
||||
ServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
|
||||
|
||||
try {
|
||||
WebSocketHandler webSocketHandler = this.handlerProvider.getHandler();
|
||||
this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, webSocketHandler);
|
||||
this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, this.handlerProvider);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// TODO
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.sockjs.AbstractSockJsSession;
|
||||
import org.springframework.sockjs.server.TransportHandler;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
@@ -53,7 +54,7 @@ public abstract class AbstractHttpReceivingTransportHandler implements Transport
|
||||
|
||||
@Override
|
||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
|
||||
HandlerProvider<WebSocketHandler> webSocketHandler, AbstractSockJsSession session) throws Exception {
|
||||
|
||||
if (session == null) {
|
||||
response.setStatusCode(HttpStatus.NOT_FOUND);
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.sockjs.server.ConfigurableTransportHandler;
|
||||
import org.springframework.sockjs.server.SockJsConfiguration;
|
||||
import org.springframework.sockjs.server.SockJsFrame;
|
||||
import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
/**
|
||||
@@ -55,7 +56,7 @@ public abstract class AbstractHttpSendingTransportHandler
|
||||
|
||||
@Override
|
||||
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
|
||||
HandlerProvider<WebSocketHandler> webSocketHandler, AbstractSockJsSession session) throws Exception {
|
||||
|
||||
// Set content type before writing
|
||||
response.getHeaders().setContentType(getContentType());
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
|
||||
import org.springframework.sockjs.server.TransportHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
/**
|
||||
@@ -49,9 +50,9 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
|
||||
|
||||
|
||||
public AbstractHttpServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
|
||||
WebSocketHandler webSocketHandler) {
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
|
||||
super(sessionId, sockJsConfig, webSocketHandler);
|
||||
super(sessionId, sockJsConfig, handler);
|
||||
}
|
||||
|
||||
public void setFrameFormat(FrameFormat frameFormat) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -33,9 +34,9 @@ public abstract class AbstractStreamingTransportHandler extends AbstractHttpSend
|
||||
|
||||
|
||||
@Override
|
||||
public StreamingServerSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
|
||||
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), webSocketHandler);
|
||||
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.sockjs.server.TransportType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.JavaScriptUtils;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -50,9 +51,9 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
|
||||
}
|
||||
|
||||
@Override
|
||||
public PollingServerSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
|
||||
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), webSocketHandler);
|
||||
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,15 +17,16 @@ package org.springframework.sockjs.server.transport;
|
||||
|
||||
import org.springframework.sockjs.server.SockJsConfiguration;
|
||||
import org.springframework.sockjs.server.SockJsFrame;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
public class PollingServerSockJsSession extends AbstractHttpServerSockJsSession {
|
||||
|
||||
public PollingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
|
||||
WebSocketHandler webSocketHandler) {
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
|
||||
super(sessionId, sockJsConfig, webSocketHandler);
|
||||
super(sessionId, sockJsConfig, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.springframework.sockjs.server.transport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -29,6 +27,7 @@ import org.springframework.sockjs.server.SockJsFrame;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.TextMessageHandler;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
@@ -38,8 +37,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
||||
/**
|
||||
* A SockJS implementation of {@link WebSocketHandler}. Delegates messages to and from a
|
||||
* {@link SockJsHandler} and adds SockJS message framing.
|
||||
* A wrapper around a {@link WebSocketHandler} instance that parses and adds SockJS
|
||||
* messages frames as well as sends SockJS heartbeat messages.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
@@ -50,34 +49,28 @@ public class SockJsWebSocketHandler implements TextMessageHandler {
|
||||
|
||||
private final SockJsConfiguration sockJsConfig;
|
||||
|
||||
private final WebSocketHandler webSocketHandler;
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
|
||||
private final Map<WebSocketSession, AbstractSockJsSession> sessions =
|
||||
new ConcurrentHashMap<WebSocketSession, AbstractSockJsSession>();
|
||||
private AbstractSockJsSession session;
|
||||
|
||||
// TODO: JSON library used must be configurable
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
|
||||
public SockJsWebSocketHandler(SockJsConfiguration sockJsConfig, WebSocketHandler webSocketHandler) {
|
||||
Assert.notNull(sockJsConfig, "sockJsConfig is required");
|
||||
Assert.notNull(webSocketHandler, "webSocketHandler is required");
|
||||
this.sockJsConfig = sockJsConfig;
|
||||
this.webSocketHandler = webSocketHandler;
|
||||
public SockJsWebSocketHandler(SockJsConfiguration config, HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
Assert.notNull(config, "sockJsConfig is required");
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
this.sockJsConfig = config;
|
||||
this.handlerProvider = handlerProvider;
|
||||
}
|
||||
|
||||
protected SockJsConfiguration getSockJsConfig() {
|
||||
return this.sockJsConfig;
|
||||
}
|
||||
|
||||
protected AbstractSockJsSession getSockJsSession(WebSocketSession wsSession) {
|
||||
return this.sessions.get(wsSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {
|
||||
AbstractSockJsSession session = new WebSocketServerSockJsSession(wsSession, getSockJsConfig());
|
||||
this.sessions.put(wsSession, session);
|
||||
this.session = new WebSocketServerSockJsSession(wsSession, getSockJsConfig());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,8 +82,7 @@ public class SockJsWebSocketHandler implements TextMessageHandler {
|
||||
}
|
||||
try {
|
||||
String[] messages = this.objectMapper.readValue(payload, String[].class);
|
||||
AbstractSockJsSession session = getSockJsSession(wsSession);
|
||||
session.delegateMessages(messages);
|
||||
this.session.delegateMessages(messages);
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.error("Broken data received. Terminating WebSocket connection abruptly", e);
|
||||
@@ -100,14 +92,12 @@ public class SockJsWebSocketHandler implements TextMessageHandler {
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(CloseStatus status, WebSocketSession wsSession) throws Exception {
|
||||
AbstractSockJsSession session = this.sessions.remove(wsSession);
|
||||
session.delegateConnectionClosed(status);
|
||||
this.session.delegateConnectionClosed(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(Throwable exception, WebSocketSession webSocketSession) {
|
||||
AbstractSockJsSession session = getSockJsSession(webSocketSession);
|
||||
session.delegateError(exception);
|
||||
this.session.delegateError(exception);
|
||||
}
|
||||
|
||||
private static String getSockJsSessionId(WebSocketSession wsSession) {
|
||||
@@ -127,7 +117,7 @@ public class SockJsWebSocketHandler implements TextMessageHandler {
|
||||
public WebSocketServerSockJsSession(WebSocketSession wsSession, SockJsConfiguration sockJsConfig)
|
||||
throws Exception {
|
||||
|
||||
super(getSockJsSessionId(wsSession), sockJsConfig, SockJsWebSocketHandler.this.webSocketHandler);
|
||||
super(getSockJsSessionId(wsSession), sockJsConfig, SockJsWebSocketHandler.this.handlerProvider);
|
||||
this.wsSession = wsSession;
|
||||
TextMessage message = new TextMessage(SockJsFrame.openFrame().getContent());
|
||||
this.wsSession.sendMessage(message);
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.sockjs.server.SockJsConfiguration;
|
||||
import org.springframework.sockjs.server.SockJsFrame;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -29,9 +30,9 @@ public class StreamingServerSockJsSession extends AbstractHttpServerSockJsSessio
|
||||
|
||||
|
||||
public StreamingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
|
||||
WebSocketHandler webSocketHandler) {
|
||||
HandlerProvider<WebSocketHandler> handler) {
|
||||
|
||||
super(sessionId, sockJsConfig, webSocketHandler);
|
||||
super(sessionId, sockJsConfig, handler);
|
||||
}
|
||||
|
||||
protected void flushCache() throws Exception {
|
||||
|
||||
@@ -24,8 +24,10 @@ import org.springframework.sockjs.server.SockJsConfiguration;
|
||||
import org.springframework.sockjs.server.TransportHandler;
|
||||
import org.springframework.sockjs.server.TransportType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.server.HandshakeHandler;
|
||||
import org.springframework.websocket.support.SimpleHandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -60,26 +62,19 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
|
||||
|
||||
@Override
|
||||
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
|
||||
HandlerProvider<WebSocketHandler> handler, AbstractSockJsSession session) throws Exception {
|
||||
|
||||
this.handshakeHandler.doHandshake(request, response, adaptSockJsHandler(webSocketHandler));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt the {@link SockJsHandler} to the {@link WebSocketHandler} contract for
|
||||
* exchanging SockJS message over WebSocket.
|
||||
*/
|
||||
protected WebSocketHandler adaptSockJsHandler(WebSocketHandler handler) {
|
||||
return new SockJsWebSocketHandler(this.sockJsConfig, handler);
|
||||
WebSocketHandler sockJsWrapper = new SockJsWebSocketHandler(this.sockJsConfig, handler);
|
||||
this.handshakeHandler.doHandshake(request, response, new SimpleHandlerProvider<WebSocketHandler>(sockJsWrapper));
|
||||
}
|
||||
|
||||
// HandshakeHandler methods
|
||||
|
||||
@Override
|
||||
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler) throws Exception {
|
||||
HandlerProvider<WebSocketHandler> handler) throws Exception {
|
||||
|
||||
return this.handshakeHandler.doHandshake(request, response, webSocketHandler);
|
||||
return this.handshakeHandler.doHandshake(request, response, handler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.sockjs.server.SockJsFrame.DefaultFrameFormat;
|
||||
import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
|
||||
import org.springframework.sockjs.server.TransportType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -50,9 +51,9 @@ public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHand
|
||||
return new DefaultFrameFormat("%s\n");
|
||||
}
|
||||
|
||||
public PollingServerSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
|
||||
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler> handler) {
|
||||
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
|
||||
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), webSocketHandler);
|
||||
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@@ -13,82 +13,36 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.websocket;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
|
||||
/**
|
||||
* A strategy for obtaining a handler instance that is scoped to external lifecycle events
|
||||
* such as the opening and closing of a WebSocket connection.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class HandlerProvider<T> implements BeanFactoryAware {
|
||||
public interface HandlerProvider<T> {
|
||||
|
||||
private Log logger = LogFactory.getLog(this.getClass());
|
||||
/**
|
||||
* Whether the provided handler is a shared instance or not.
|
||||
*/
|
||||
boolean isSingleton();
|
||||
|
||||
private final T handlerBean;
|
||||
/**
|
||||
* The type of handler provided.
|
||||
*/
|
||||
Class<?> getHandlerType();
|
||||
|
||||
private final Class<? extends T> handlerClass;
|
||||
/**
|
||||
* Obtain the handler instance, either shared or created every time.
|
||||
*/
|
||||
T getHandler();
|
||||
|
||||
private AutowireCapableBeanFactory beanFactory;
|
||||
|
||||
|
||||
public HandlerProvider(T handlerBean) {
|
||||
Assert.notNull(handlerBean, "handlerBean is required");
|
||||
this.handlerBean = handlerBean;
|
||||
this.handlerClass = null;
|
||||
}
|
||||
|
||||
public HandlerProvider(Class<? extends T> handlerClass) {
|
||||
Assert.notNull(handlerClass, "handlerClass is required");
|
||||
this.handlerBean = null;
|
||||
this.handlerClass = handlerClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (beanFactory instanceof AutowireCapableBeanFactory) {
|
||||
this.beanFactory = (AutowireCapableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
public void setLogger(Log logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return (this.handlerBean != null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends T> getHandlerType() {
|
||||
if (this.handlerClass != null) {
|
||||
return this.handlerClass;
|
||||
}
|
||||
return (Class<? extends T>) ClassUtils.getUserClass(this.handlerBean.getClass());
|
||||
}
|
||||
|
||||
public T getHandler() {
|
||||
if (this.handlerBean != null) {
|
||||
if (logger != null && logger.isTraceEnabled()) {
|
||||
logger.trace("Returning handler singleton " + this.handlerBean);
|
||||
}
|
||||
return this.handlerBean;
|
||||
}
|
||||
Assert.isTrue(this.beanFactory != null, "BeanFactory is required to initialize handler instances.");
|
||||
if (logger != null && logger.isTraceEnabled()) {
|
||||
logger.trace("Creating handler of type " + this.handlerClass);
|
||||
}
|
||||
return this.beanFactory.createBean(this.handlerClass);
|
||||
}
|
||||
/**
|
||||
* Callback to destroy a previously created handler instance if it is not shared.
|
||||
*/
|
||||
void destroy(T handler);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.websocket.client;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
@@ -36,13 +37,10 @@ import org.springframework.websocket.WebSocketSession;
|
||||
public interface WebSocketClient {
|
||||
|
||||
|
||||
WebSocketSession doHandshake(WebSocketHandler handler, String uriTemplate, Object... uriVariables)
|
||||
throws WebSocketConnectFailureException;
|
||||
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler,
|
||||
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException;
|
||||
|
||||
WebSocketSession doHandshake(WebSocketHandler handler, URI uri)
|
||||
throws WebSocketConnectFailureException;
|
||||
|
||||
WebSocketSession doHandshake(WebSocketHandler handler, HttpHeaders headers, URI uri)
|
||||
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler, HttpHeaders headers, URI uri)
|
||||
throws WebSocketConnectFailureException;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
import org.springframework.websocket.support.SimpleHandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -32,7 +33,7 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
|
||||
|
||||
private final WebSocketClient client;
|
||||
|
||||
private final HandlerProvider<WebSocketHandler> webSocketHandlerProvider;
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
|
||||
private WebSocketSession webSocketSession;
|
||||
|
||||
@@ -43,8 +44,16 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
|
||||
WebSocketHandler webSocketHandler, String uriTemplate, Object... uriVariables) {
|
||||
|
||||
super(uriTemplate, uriVariables);
|
||||
this.webSocketHandlerProvider = new HandlerProvider<WebSocketHandler>(webSocketHandler);
|
||||
this.client = webSocketClient;
|
||||
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler>(webSocketHandler);
|
||||
}
|
||||
|
||||
public WebSocketConnectionManager(WebSocketClient webSocketClient,
|
||||
HandlerProvider<WebSocketHandler> handlerProvider, String uriTemplate, Object... uriVariables) {
|
||||
|
||||
super(uriTemplate, uriVariables);
|
||||
this.client = webSocketClient;
|
||||
this.handlerProvider = handlerProvider;
|
||||
}
|
||||
|
||||
public void setSubProtocols(List<String> subProtocols) {
|
||||
@@ -57,10 +66,9 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
|
||||
|
||||
@Override
|
||||
protected void openConnection() throws Exception {
|
||||
WebSocketHandler webSocketHandler = this.webSocketHandlerProvider.getHandler();
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setSecWebSocketProtocol(this.subProtocols);
|
||||
this.webSocketSession = this.client.doHandshake(webSocketHandler, headers, getUri());
|
||||
this.webSocketSession = this.client.doHandshake(this.handlerProvider, headers, getUri());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,8 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.support.BeanCreatingHandlerProvider;
|
||||
import org.springframework.websocket.support.SimpleHandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -32,28 +34,29 @@ import org.springframework.websocket.HandlerProvider;
|
||||
public class AnnotatedEndpointConnectionManager extends EndpointConnectionManagerSupport
|
||||
implements BeanFactoryAware {
|
||||
|
||||
private final HandlerProvider<Object> endpointProvider;
|
||||
private final HandlerProvider<Object> handlerProvider;
|
||||
|
||||
|
||||
public AnnotatedEndpointConnectionManager(Class<?> endpointClass, String uriTemplate, Object... uriVariables) {
|
||||
super(uriTemplate, uriVariables);
|
||||
this.endpointProvider = new HandlerProvider<Object>(endpointClass);
|
||||
}
|
||||
|
||||
public AnnotatedEndpointConnectionManager(Object endpointBean, String uriTemplate, Object... uriVariables) {
|
||||
super(uriTemplate, uriVariables);
|
||||
this.endpointProvider = new HandlerProvider<Object>(endpointBean);
|
||||
this.handlerProvider = new SimpleHandlerProvider<Object>(endpointBean);
|
||||
}
|
||||
|
||||
public AnnotatedEndpointConnectionManager(Class<?> endpointClass, String uriTemplate, Object... uriVariables) {
|
||||
super(uriTemplate, uriVariables);
|
||||
this.handlerProvider = new BeanCreatingHandlerProvider<Object>(endpointClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.endpointProvider.setBeanFactory(beanFactory);
|
||||
if (this.handlerProvider instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.handlerProvider).setBeanFactory(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void openConnection() throws Exception {
|
||||
Object endpoint = this.endpointProvider.getHandler();
|
||||
Object endpoint = this.handlerProvider.getHandler();
|
||||
Session session = getWebSocketContainer().connectToServer(endpoint, getUri());
|
||||
updateSession(session);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.support.BeanCreatingHandlerProvider;
|
||||
import org.springframework.websocket.support.SimpleHandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -43,19 +45,19 @@ public class EndpointConnectionManager extends EndpointConnectionManagerSupport
|
||||
|
||||
private final ClientEndpointConfig.Builder configBuilder = ClientEndpointConfig.Builder.create();
|
||||
|
||||
private final HandlerProvider<Endpoint> endpointProvider;
|
||||
private final HandlerProvider<Endpoint> handlerProvider;
|
||||
|
||||
|
||||
public EndpointConnectionManager(Endpoint endpointBean, String uriTemplate, Object... uriVariables) {
|
||||
super(uriTemplate, uriVariables);
|
||||
Assert.notNull(endpointBean, "endpointBean is required");
|
||||
this.endpointProvider = new HandlerProvider<Endpoint>(endpointBean);
|
||||
this.handlerProvider = new SimpleHandlerProvider<Endpoint>(endpointBean);
|
||||
}
|
||||
|
||||
public EndpointConnectionManager(Class<? extends Endpoint> endpointClass, String uriTemplate, Object... uriVars) {
|
||||
super(uriTemplate, uriVars);
|
||||
Assert.notNull(endpointClass, "endpointClass is required");
|
||||
this.endpointProvider = new HandlerProvider<Endpoint>(endpointClass);
|
||||
this.handlerProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass);
|
||||
}
|
||||
|
||||
public void setSubProtocols(String... subprotocols) {
|
||||
@@ -80,12 +82,14 @@ public class EndpointConnectionManager extends EndpointConnectionManagerSupport
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.endpointProvider.setBeanFactory(beanFactory);
|
||||
if (this.handlerProvider instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.handlerProvider).setBeanFactory(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void openConnection() throws Exception {
|
||||
Endpoint endpoint = this.endpointProvider.getHandler();
|
||||
Endpoint endpoint = this.handlerProvider.getHandler();
|
||||
ClientEndpointConfig endpointConfig = this.configBuilder.build();
|
||||
Session session = getWebSocketContainer().connectToServer(endpoint, endpointConfig, getUri());
|
||||
updateSession(session);
|
||||
|
||||
@@ -31,6 +31,7 @@ import javax.websocket.WebSocketContainer;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
import org.springframework.websocket.client.WebSocketClient;
|
||||
@@ -40,6 +41,7 @@ import org.springframework.websocket.endpoint.WebSocketHandlerEndpoint;
|
||||
|
||||
|
||||
/**
|
||||
* A standard Java {@link WebSocketClient}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
@@ -57,21 +59,16 @@ public class StandardWebSocketClient implements WebSocketClient {
|
||||
this.webSocketContainer = container;
|
||||
}
|
||||
|
||||
public WebSocketSession doHandshake(WebSocketHandler handler, String uriTemplate,
|
||||
Object... uriVariables) throws WebSocketConnectFailureException {
|
||||
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler,
|
||||
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(uriVariables).encode().toUri();
|
||||
return doHandshake(handler, uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketSession doHandshake(WebSocketHandler handler, URI uri) throws WebSocketConnectFailureException {
|
||||
return doHandshake(handler, null, uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketSession doHandshake(WebSocketHandler handler, final HttpHeaders httpHeaders, URI uri)
|
||||
throws WebSocketConnectFailureException {
|
||||
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler> handler,
|
||||
final HttpHeaders httpHeaders, URI uri) throws WebSocketConnectFailureException {
|
||||
|
||||
Endpoint endpoint = new WebSocketHandlerEndpoint(handler);
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.websocket.endpoint;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Endpoint;
|
||||
import javax.websocket.EndpointConfig;
|
||||
@@ -27,14 +24,15 @@ import javax.websocket.MessageHandler;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.BinaryMessage;
|
||||
import org.springframework.websocket.BinaryMessageHandler;
|
||||
import org.springframework.websocket.CloseStatus;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.PartialMessageHandler;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
import org.springframework.websocket.TextMessage;
|
||||
import org.springframework.websocket.TextMessageHandler;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.WebSocketSession;
|
||||
|
||||
|
||||
/**
|
||||
@@ -47,14 +45,17 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
|
||||
private static Log logger = LogFactory.getLog(WebSocketHandlerEndpoint.class);
|
||||
|
||||
private final WebSocketHandler webSocketHandler;
|
||||
private final HandlerProvider<WebSocketHandler> handlerProvider;
|
||||
|
||||
private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<String, WebSocketSession>();
|
||||
private final WebSocketHandler handler;
|
||||
|
||||
private WebSocketSession webSocketSession;
|
||||
|
||||
|
||||
public WebSocketHandlerEndpoint(WebSocketHandler handler) {
|
||||
Assert.notNull(handler, "webSocketHandler is required");
|
||||
this.webSocketHandler = handler;
|
||||
public WebSocketHandlerEndpoint(HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
this.handlerProvider = handlerProvider;
|
||||
this.handler = handlerProvider.getHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,10 +64,9 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
logger.debug("Client connected, WebSocket session id=" + session.getId() + ", uri=" + session.getRequestURI());
|
||||
}
|
||||
try {
|
||||
WebSocketSession webSocketSession = new StandardWebSocketSession(session);
|
||||
this.sessions.put(session.getId(), webSocketSession);
|
||||
this.webSocketSession = new StandardWebSocketSession(session);
|
||||
|
||||
if (this.webSocketHandler instanceof TextMessageHandler) {
|
||||
if (this.handler instanceof TextMessageHandler) {
|
||||
session.addMessageHandler(new MessageHandler.Whole<String>() {
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
@@ -74,8 +74,8 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (this.webSocketHandler instanceof BinaryMessageHandler) {
|
||||
if (this.webSocketHandler instanceof PartialMessageHandler) {
|
||||
else if (this.handler instanceof BinaryMessageHandler) {
|
||||
if (this.handler instanceof PartialMessageHandler) {
|
||||
session.addMessageHandler(new MessageHandler.Partial<byte[]>() {
|
||||
@Override
|
||||
public void onMessage(byte[] messagePart, boolean isLast) {
|
||||
@@ -93,10 +93,10 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.warn("WebSocketHandler handles neither text nor binary messages: " + this.webSocketHandler);
|
||||
logger.warn("WebSocketHandler handles neither text nor binary messages: " + this.handler);
|
||||
}
|
||||
|
||||
this.webSocketHandler.afterConnectionEstablished(webSocketSession);
|
||||
this.handler.afterConnectionEstablished(this.webSocketSession);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// TODO
|
||||
@@ -108,11 +108,9 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Received message for WebSocket session id=" + session.getId() + ": " + message);
|
||||
}
|
||||
WebSocketSession wsSession = getWebSocketSession(session);
|
||||
Assert.notNull(wsSession, "WebSocketSession not found");
|
||||
try {
|
||||
TextMessage textMessage = new TextMessage(message);
|
||||
((TextMessageHandler) webSocketHandler).handleTextMessage(textMessage, wsSession);
|
||||
((TextMessageHandler) handler).handleTextMessage(textMessage, this.webSocketSession);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// TODO
|
||||
@@ -124,11 +122,9 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Received binary data for WebSocket session id=" + session.getId());
|
||||
}
|
||||
WebSocketSession wsSession = getWebSocketSession(session);
|
||||
Assert.notNull(wsSession, "WebSocketSession not found");
|
||||
try {
|
||||
BinaryMessage binaryMessage = new BinaryMessage(message, isLast);
|
||||
((BinaryMessageHandler) webSocketHandler).handleBinaryMessage(binaryMessage, wsSession);
|
||||
((BinaryMessageHandler) handler).handleBinaryMessage(binaryMessage, this.webSocketSession);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// TODO
|
||||
@@ -142,32 +138,23 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
logger.debug("Client disconnected, WebSocket session id=" + session.getId() + ", " + reason);
|
||||
}
|
||||
try {
|
||||
WebSocketSession wsSession = this.sessions.remove(session.getId());
|
||||
if (wsSession != null) {
|
||||
CloseStatus closeStatus = new CloseStatus(reason.getCloseCode().getCode(), reason.getReasonPhrase());
|
||||
this.webSocketHandler.afterConnectionClosed(closeStatus, wsSession);
|
||||
}
|
||||
else {
|
||||
Assert.notNull(wsSession, "No WebSocket session");
|
||||
}
|
||||
CloseStatus closeStatus = new CloseStatus(reason.getCloseCode().getCode(), reason.getReasonPhrase());
|
||||
this.handler.afterConnectionClosed(closeStatus, this.webSocketSession);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// TODO
|
||||
logger.error("Error while processing session closing", ex);
|
||||
}
|
||||
finally {
|
||||
this.handlerProvider.destroy(this.handler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(javax.websocket.Session session, Throwable exception) {
|
||||
logger.error("Error for WebSocket session id=" + session.getId(), exception);
|
||||
try {
|
||||
WebSocketSession wsSession = getWebSocketSession(session);
|
||||
if (wsSession != null) {
|
||||
this.webSocketHandler.handleError(exception, wsSession);
|
||||
}
|
||||
else {
|
||||
logger.warn("WebSocketSession not found. Perhaps onError was called after onClose?");
|
||||
}
|
||||
this.handler.handleError(exception, this.webSocketSession);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// TODO
|
||||
@@ -175,8 +162,4 @@ public class WebSocketHandlerEndpoint extends Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
private WebSocketSession getWebSocketSession(javax.websocket.Session session) {
|
||||
return this.sessions.get(session.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -87,7 +88,7 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
|
||||
|
||||
@Override
|
||||
public final boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler webSocketHandler) throws Exception {
|
||||
HandlerProvider<WebSocketHandler> handler) throws Exception {
|
||||
|
||||
logger.debug("Starting handshake for " + request.getURI());
|
||||
|
||||
@@ -135,10 +136,10 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
|
||||
response.flush();
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Upgrading with " + webSocketHandler);
|
||||
logger.trace("Upgrading with " + handler);
|
||||
}
|
||||
|
||||
this.requestUpgradeStrategy.upgrade(request, response, selectedProtocol, webSocketHandler);
|
||||
this.requestUpgradeStrategy.upgrade(request, response, selectedProtocol, handler);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.websocket.server;
|
||||
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -29,16 +30,8 @@ import org.springframework.websocket.WebSocketHandler;
|
||||
*/
|
||||
public interface HandshakeHandler {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param webSocketMessageHandler the handler to process WebSocket messages with
|
||||
* @return a boolean indicating whether the handshake negotiation was successful
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler)
|
||||
throws Exception;
|
||||
|
||||
boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
HandlerProvider<WebSocketHandler> handler) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.websocket.server;
|
||||
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
|
||||
|
||||
@@ -39,9 +40,9 @@ public interface RequestUpgradeStrategy {
|
||||
* Perform runtime specific steps to complete the upgrade.
|
||||
* Invoked only if the handshake is successful.
|
||||
*
|
||||
* @param webSocketHandler the handler for WebSocket messages
|
||||
* @param handler the handler for WebSocket messages
|
||||
*/
|
||||
void upgrade(ServerHttpRequest request, ServerHttpResponse response, String selectedProtocol,
|
||||
WebSocketHandler webSocketHandler) throws Exception;
|
||||
HandlerProvider<WebSocketHandler> handler) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.endpoint.WebSocketHandlerEndpoint;
|
||||
import org.springframework.websocket.support.BeanCreatingHandlerProvider;
|
||||
import org.springframework.websocket.support.SimpleHandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -54,11 +56,9 @@ import org.springframework.websocket.endpoint.WebSocketHandlerEndpoint;
|
||||
*/
|
||||
public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAware {
|
||||
|
||||
private static Log logger = LogFactory.getLog(EndpointRegistration.class);
|
||||
|
||||
private final String path;
|
||||
|
||||
private final HandlerProvider<Endpoint> endpointProvider;
|
||||
private final HandlerProvider<Endpoint> handlerProvider;
|
||||
|
||||
private List<Class<? extends Encoder>> encoders = new ArrayList<Class<? extends Encoder>>();
|
||||
|
||||
@@ -84,16 +84,14 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
|
||||
Assert.hasText(path, "path must not be empty");
|
||||
Assert.notNull(endpointClass, "endpointClass is required");
|
||||
this.path = path;
|
||||
this.endpointProvider = new HandlerProvider<Endpoint>(endpointClass);
|
||||
this.endpointProvider.setLogger(logger);
|
||||
this.handlerProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass);
|
||||
}
|
||||
|
||||
public EndpointRegistration(String path, Endpoint endpointBean) {
|
||||
Assert.hasText(path, "path must not be empty");
|
||||
Assert.notNull(endpointBean, "endpointBean is required");
|
||||
this.path = path;
|
||||
this.endpointProvider = new HandlerProvider<Endpoint>(endpointBean);
|
||||
this.endpointProvider.setLogger(logger);
|
||||
this.handlerProvider = new SimpleHandlerProvider<Endpoint>(endpointBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,12 +100,13 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends Endpoint> getEndpointClass() {
|
||||
return this.endpointProvider.getHandlerType();
|
||||
return (Class<? extends Endpoint>) this.handlerProvider.getHandlerType();
|
||||
}
|
||||
|
||||
public Endpoint getEndpoint() {
|
||||
return this.endpointProvider.getHandler();
|
||||
return this.handlerProvider.getHandler();
|
||||
}
|
||||
|
||||
public void setSubprotocols(List<String> subprotocols) {
|
||||
@@ -193,7 +192,9 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.endpointProvider.setBeanFactory(beanFactory);
|
||||
if (this.handlerProvider instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.handlerProvider).setBeanFactory(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,88 +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.server.support;
|
||||
|
||||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public abstract class AbstractEndpointContainerFactoryBean implements FactoryBean<WebSocketContainer>, InitializingBean {
|
||||
|
||||
private WebSocketContainer container;
|
||||
|
||||
|
||||
public void setAsyncSendTimeout(long timeoutInMillis) {
|
||||
this.container.setAsyncSendTimeout(timeoutInMillis);
|
||||
}
|
||||
|
||||
public long getAsyncSendTimeout() {
|
||||
return this.container.getDefaultAsyncSendTimeout();
|
||||
}
|
||||
|
||||
public void setMaxSessionIdleTimeout(long timeoutInMillis) {
|
||||
this.container.setDefaultMaxSessionIdleTimeout(timeoutInMillis);
|
||||
}
|
||||
|
||||
public long getMaxSessionIdleTimeout() {
|
||||
return this.container.getDefaultMaxSessionIdleTimeout();
|
||||
}
|
||||
|
||||
public void setMaxTextMessageBufferSize(int bufferSize) {
|
||||
this.container.setDefaultMaxTextMessageBufferSize(bufferSize);
|
||||
}
|
||||
|
||||
public int getMaxTextMessageBufferSize() {
|
||||
return this.container.getDefaultMaxTextMessageBufferSize();
|
||||
}
|
||||
|
||||
public void setMaxBinaryMessageBufferSize(int bufferSize) {
|
||||
this.container.setDefaultMaxBinaryMessageBufferSize(bufferSize);
|
||||
}
|
||||
|
||||
public int getMaxBinaryMessageBufferSize() {
|
||||
return this.container.getDefaultMaxBinaryMessageBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.container = getContainer();
|
||||
}
|
||||
|
||||
protected abstract WebSocketContainer getContainer();
|
||||
|
||||
@Override
|
||||
public WebSocketContainer getObject() throws Exception {
|
||||
return this.container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return WebSocketContainer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.endpoint.WebSocketHandlerEndpoint;
|
||||
import org.springframework.websocket.server.RequestUpgradeStrategy;
|
||||
@@ -41,12 +42,12 @@ public abstract class AbstractEndpointUpgradeStrategy implements RequestUpgradeS
|
||||
|
||||
@Override
|
||||
public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
|
||||
String protocol, WebSocketHandler webSocketHandler) throws Exception {
|
||||
String protocol, HandlerProvider<WebSocketHandler> handler) throws Exception {
|
||||
|
||||
upgradeInternal(request, response, protocol, adaptWebSocketHandler(webSocketHandler));
|
||||
upgradeInternal(request, response, protocol, adaptWebSocketHandler(handler));
|
||||
}
|
||||
|
||||
protected Endpoint adaptWebSocketHandler(WebSocketHandler handler) {
|
||||
protected Endpoint adaptWebSocketHandler(HandlerProvider<WebSocketHandler> handler) {
|
||||
return new WebSocketHandlerEndpoint(handler);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,6 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
@@ -36,6 +33,7 @@ import org.springframework.websocket.HandlerProvider;
|
||||
import org.springframework.websocket.WebSocketHandler;
|
||||
import org.springframework.websocket.server.DefaultHandshakeHandler;
|
||||
import org.springframework.websocket.server.HandshakeHandler;
|
||||
import org.springframework.websocket.support.SimpleHandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -44,7 +42,7 @@ import org.springframework.websocket.server.HandshakeHandler;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WebSocketHttpRequestHandler implements HttpRequestHandler, BeanFactoryAware {
|
||||
public class WebSocketHttpRequestHandler implements HttpRequestHandler {
|
||||
|
||||
private HandshakeHandler handshakeHandler;
|
||||
|
||||
@@ -53,13 +51,13 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler, BeanFact
|
||||
|
||||
public WebSocketHttpRequestHandler(WebSocketHandler webSocketHandler) {
|
||||
Assert.notNull(webSocketHandler, "webSocketHandler is required");
|
||||
this.handlerProvider = new HandlerProvider<WebSocketHandler>(webSocketHandler);
|
||||
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler>(webSocketHandler);
|
||||
this.handshakeHandler = new DefaultHandshakeHandler();
|
||||
}
|
||||
|
||||
public WebSocketHttpRequestHandler( Class<? extends WebSocketHandler> webSocketHandlerClass) {
|
||||
Assert.notNull(webSocketHandlerClass, "webSocketHandlerClass is required");
|
||||
this.handlerProvider = new HandlerProvider<WebSocketHandler>(webSocketHandlerClass);
|
||||
public WebSocketHttpRequestHandler( HandlerProvider<WebSocketHandler> handlerProvider) {
|
||||
Assert.notNull(handlerProvider, "handlerProvider is required");
|
||||
this.handlerProvider = handlerProvider;
|
||||
}
|
||||
|
||||
public void setHandshakeHandler(HandshakeHandler handshakeHandler) {
|
||||
@@ -67,11 +65,6 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler, BeanFact
|
||||
this.handshakeHandler = handshakeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.handlerProvider.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
@@ -80,8 +73,7 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler, BeanFact
|
||||
ServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
|
||||
|
||||
try {
|
||||
WebSocketHandler webSocketHandler = this.handlerProvider.getHandler();
|
||||
this.handshakeHandler.doHandshake(httpRequest, httpResponse, webSocketHandler);
|
||||
this.handshakeHandler.doHandshake(httpRequest, httpResponse, this.handlerProvider);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// TODO
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link HandlerProvider} that uses {@link AutowireCapableBeanFactory#createBean(Class)
|
||||
* creating a fresh instance every time #getHandler() is called.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class BeanCreatingHandlerProvider<T> implements HandlerProvider<T>, BeanFactoryAware {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BeanCreatingHandlerProvider.class);
|
||||
|
||||
private final Class<? extends T> handlerClass;
|
||||
|
||||
private AutowireCapableBeanFactory beanFactory;
|
||||
|
||||
|
||||
public BeanCreatingHandlerProvider(Class<? extends T> handlerClass) {
|
||||
Assert.notNull(handlerClass, "handlerClass is required");
|
||||
this.handlerClass = handlerClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (beanFactory instanceof AutowireCapableBeanFactory) {
|
||||
this.beanFactory = (AutowireCapableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Class<? extends T> getHandlerType() {
|
||||
return this.handlerClass;
|
||||
}
|
||||
|
||||
public T getHandler() {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Creating instance for handler type " + this.handlerClass);
|
||||
}
|
||||
if (this.beanFactory == null) {
|
||||
logger.warn("No BeanFactory available, attempting to use default constructor");
|
||||
return BeanUtils.instantiate(this.handlerClass);
|
||||
}
|
||||
else {
|
||||
return this.beanFactory.createBean(this.handlerClass);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(T handler) {
|
||||
if (this.beanFactory != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Destroying handler instance " + handler);
|
||||
}
|
||||
this.beanFactory.destroyBean(handler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BeanCreatingHandlerProvider [handlerClass=" + handlerClass + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.websocket.HandlerProvider;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link HandlerProvider} that returns a singleton instance.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SimpleHandlerProvider<T> implements HandlerProvider<T> {
|
||||
|
||||
private final T handler;
|
||||
|
||||
|
||||
public SimpleHandlerProvider(T handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getHandlerType() {
|
||||
return ClassUtils.getUserClass(this.handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(T handler) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleHandlerProvider [handler=" + handler + "]";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user