我遇到了尝试使用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>