在Redis中存储Web套接字会话

时间:2018-12-06 11:35:28

标签: java tomcat websocket redis

我在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中,因为它是不可序列化的对象,因此必须将其维护在本地内存中。我希望避免这种情况,因为如果服务器重新启动或进行负载平衡,我不想丢失数据。

如何实现?

1 个答案:

答案 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规范)几乎需要对序列化的支持,所以...即使不赞成使用,我也看不到很快就会去任何地方。