我在Tomcat中部署了Web套接字服务器端点,如下所示:
@ServerEndpoint(value="/alerts/{username}/{sessionId}/{token}",
decoders = AlertDTODecoder.class,
encoders = AlertDTOEncoder.class )
public class AlertWebSocketEndpoint {
@OnOpen
public void onOpen(Session session,
@PathParam("username") String username,
@PathParam("sessionId") String sessionId,
@PathParam("token") String token) throws IOException {
String origToken = TokenCacheServiceImpl.getInstance().getToken(username, sessionId);
if ( origToken == null || !origToken.equals(token)) {
session.close();
}else {
AlertSession.getInstance().addUserSession(username, session);
}
}
@OnClose
public void onClose(Session session, @PathParam("username") String username) throws Exception {
AlertSession.getInstance().removeUserSession(username, session);
session.close();
}
}
AlertSession是一个单例类,我在其中维护会话的缓存。
TokenCacheServiceImpl用于在REDIS中缓存与每个用户相对应的令牌。
我不能将会话存储在REDIS中,因为它是不可序列化的对象,因此必须将其维护在本地内存中。我希望避免这种情况,因为如果服务器重新启动或进行负载平衡,我不想丢失数据。
如何实现?
答案 0 :(得分:0)
如果不进行大量工作,您将无法存储任意的非serializable
对象。
但是,如果您知道已经存储了哪种对象,那么您当然可以编写自己的序列化器。没有什么可以说数据必须是二进制的。您可以使用XML,JSON或某些组合存储系统。
您可以限制您的应用程序,使其仅存储某些类型的对象吗?例如,如果您仅存储基元(以及其装箱的样式)和集合或这些内容,则只需很少的代码即可完成此操作。如果没有,请准备编写更多代码。
将会话对象的代码更改为Serializable
,然后仅使用Java序列化完成工作,可能会更容易。
请注意,Java序列化的未来是不确定的。归档了一个非常老的JEP来删除序列化,但是it was withdrawn。最近的安全问题促使一些人support the removal of serialization from future Java versions。第二篇文章特别提到“ [r]移除序列化是一个长期目标,是Project Amber的一部分”,但我在Project Amber中看不到任何涉及序列化的东西。
此外,某些现有的Java规范(Java EE的一部分,包括Servlet规范)几乎需要对序列化的支持,所以...即使不赞成使用,我也看不到很快就会去任何地方。