Java WebSocket 获取 HttpSession

Java WebSocket Session 大约 2696 字

原理

WebSocket在建立时握手阶段是建立在HTTP协议之上,握手成功升级为TCP长链接。在握手阶段获取HttpSession,设置到WebSocketSession中即可。

前提

HTTP服务端口必须和WebSocket端口为同一个(比如:8080),不能一个使用代理端口,一个直接使用服务端口。

代码

配置类:从握手阶段获取到HttpSession,如果不为null,则放入WebSocketSession中的用户配置Map中。

public class WebSocketServerConfigurator extends ServerEndpointConfig.Configurator {

    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        if (httpSession != null) {
            Map<String, Object> userProperties = sec.getUserProperties();
            userProperties.put(HttpSession.class.getName(), httpSession);
        }
    }
}

设置自定义的Configurator

@ServerEndpoint(value = "/test/ws/{username}", configurator = WebSocketServerConfigurator.class)
public class WebSocketServer {

    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session) {
        HttpSession httpSession = (HttpSession) session.getUserProperties().get(HttpSession.class.getName());
        System.out.println("onOpen#" + httpSession);

        // 最大超时时间 60 秒
        session.setMaxIdleTimeout(TimeUnit.MINUTES.toMillis(5));
        session.setMaxBinaryMessageBufferSize(8192 * 1024); // 8KB
        session.setMaxTextMessageBufferSize(8192 * 1024); // 字符数
        session.getAsyncRemote().sendText("123");
    }

    // ... 省略了其他事件
}

注意

如果一开始没有请求没有初始化HttpSession(如刚进入网页就连接WebSocket),则WebSocket握手阶段HandshakeRequest获取到的HttpSessionnull,此时再在别的Servlet中设置HttpSessionWebSocket中始终获取不到HttpSession

解决办法

方法一

连接WebSocket操作放在初始化了HttpSession之后。比如登录后写入相关信息到HttpSession

方法二

增加ServertRequestListener,在每次请求初始化时都去获取一次HttpSession(如果请求没有关联的HttpSession,则创建一个新的),这样此次用户浏览网页时都是关联的同一个Session

@WebListener
public class MyServletListener implements ServletRequestListener {

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        HttpSession session = request.getSession();
        System.out.println("requestInitialized session = " + session);
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("requestDestroyed sre = " + sre);
    }

}

可以看到getSession表示:返回请求关联的 session, 若请求没有 session 则创建一个。

public interface HttpServletRequest extends ServletRequest {
    /**
     * Returns the current session associated with this request, or if the
     * request does not have a session, creates one.
     *
     * @return the <code>HttpSession</code> associated with this request
     * @see #getSession(boolean)
     */
    public HttpSession getSession();
}
阅读 790 · 发布于 2021-04-21

————        END        ————

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
随便看看 换一批