我遇到了尝试使用Spring WebSockets创建聊天的问题。
春季版本-4.3.1。
我创建了一个类ChatWebSocketHandler extending TextWebSocketHandler。这是websocket的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行以确保这一点。
我得到了两个用户(Developer和Alex)的输出:

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


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

最佳答案

这是一个古老的问题,但仍未得到解决,因此很好地解决它。

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

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>

10-04 19:07