Spring使用websocket处理程序bean作为单例,尽管它的原型范围

时间:2016-07-17 08:09:43

标签: java spring-websocket

我遇到了尝试使用Spring WebSockets创建聊天的问题 春季版 - 4.3.1。
我创建了一个类ChatWebSocketHandler extending TextWebSocketHandler。这是websockets的XML配置:

<websocket:handlers>
    <websocket:mapping path="/websocket/chat" handler="chatWebSocketHandler" />
    <websocket:handshake-interceptors>
        <bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor" />
    </websocket:handshake-interceptors>
</websocket:handlers>

<bean name="chatWebSocketHandler" class="org.kolokolov.chat.controller.ChatWebSocketHandler" scope="prototype" />

如您所见,我为此bean定义了原型范围 这样做我期望Spring会为连接聊天的任何新用户创建一个ChatWebSocketHandler的新实例。我需要它,因为这个bean是有状态的,因为连接用户的UserProfile在建立连接时被写入它的字段。
这是代码的一部分

public class ChatWebSocketHandler extends TextWebSocketHandler {
private UserProfile user;
private static final Map<String, WebSocketSession> connections = new ConcurrentHashMap<>();

@Autowired
MessageService messageService;

public static Map<String, WebSocketSession> getConnections() {
    return connections;
}

@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
    this.user = (UserProfile) webSocketSession.getAttributes().get("user");
    connections.put(user.getNickname(), webSocketSession);
    String message = String.format("%s %s", user.getNickname(), "has joined.");
    broadcast(new Message(MessageType.MESSAGE, message, "[SERVER]").toJson());
    broadcast(new Message(MessageType.USER_LIST, getLoggedUsersList()).toJson());
    System.out.println(this + " : " + user.getNickname());
    System.out.println(connections);
}

对于单个用户,一切正常,直到我尝试将第二个用户连接到聊天。 据我所知,没有为新用户创建ChatWebSocketHandler的新实例。我将第一个System.out.println行添加到afterConnectionEstablished方法以确保它。 我有两个用户(开发人员和亚历克斯)的输出:

org.kolokolov.chat.controller.ChatWebSocketHandler@2c1b0d6d : Developer
org.kolokolov.chat.controller.ChatWebSocketHandler@2c1b0d6d : Alex

如您所见,查看哈希码,两个用户都使用相同的ChatWebSocketHandler实例。
为避免这种情况,我应该考虑什么?

1 个答案:

答案 0 :(得分:0)

这是一个老问题,但仍然没有答案,所以处理它会很好。

对于具有以下代码的端点:

package com.my.company;

public class ChatWebSocketHandler extends TextWebSocketHandler {
    //override needed methods
}

有一个org.springframework.web.socket.handler.PerConnectionWebSocketHandler类可以帮助您实现拥有一个处理程序连接/实例的目标。 XML配置如下:

<bean id="chatPerConnectionHandler" class="org.springframework.web.socket.handler.PerConnectionWebSocketHandler">
    <constructor-arg>
        <value type="java.lang.Class">com.my.company.ChatWebSocketHandler</value>
    </constructor-arg>
</bean>

<websocket:handlers>
    <websocket:mapping path="/chat" handler="chatPerConnectionHandler" />
 <!-- your config here -->
</websocket:handlers>