spring websocket 中获取HttpSession

背景

一个普通网站,用户登录后,将用户信息存在HttpSession中。现在网站需要加入即时聊天功能,打算使用Websocket实现,需要在Websocket中拿到HttpSession来表示用户。

    /**
     * 交流
     * @param chatMessage
     */
    @MessageMapping("/chat")
    public void chat(HttpSession session, @RequestBody ChatMessage chatMessage) {
        User user = (User)session.get("user");    // error
        chatService.chat(user,chatMessage);
    }

普通的注入HttpSession是不行的,因为Websocket连接建立后,并不会HTTP协议那样,每次传输数据都会带上sessionid。

解决思路

在Websocket连接建立阶段(此时还是HTTP协议)拦截HTTP请求,获取到HttpSesion并保存。

实现

本来想自己写个类,但发现Spring Websocket已经提供了这样的拦截器HttpSessionHandshakeInterceptor,直接使用即可。

Websocket 代理配置

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/chat");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/endpoint").setAllowedOrigins("*").addInterceptors(new HttpSessionHandshakeInterceptor()).withSockJS();
    }
}

这里和普通的Websocket配置差不多,最大的区别是addInterceptors(new HttpSessionHandshakeInterceptor()),它把HttpSessionHandshakeInterceptor加入到了拦截链中。
我们可以看一下HttpSessionHandshakeInterceptor源码中的相关方法

// 在握手完成前(连接建立阶段)
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        HttpSession session = this.getSession(request);     
        if (session != null) {
            if (this.isCopyHttpSessionId()) {
                attributes.put("HTTP.SESSION.ID", session.getId());  // 保存 sessionid
            }

            Enumeration names = session.getAttributeNames();

            while(true) {
                String name;
                do {
                    if (!names.hasMoreElements()) {
                        return true;
                    }

                    name = (String)names.nextElement();
                } while(!this.isCopyAllAttributes() && !this.getAttributeNames().contains(name));

                attributes.put(name, session.getAttribute(name));    // 保存HttpSession中的信息
            }
        } else {
            return true;
        }
}

// 获取HttpSession
private HttpSession getSession(ServerHttpRequest request) {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverRequest = (ServletServerHttpRequest)request;
            return serverRequest.getServletRequest().getSession(this.isCreateSession());
        } else {
            return null;
        }
}

通过源码我们可以知道,HttpSessionHandshakeInterceptor将HttpSession中的值保存到了一个Map里面,通过搜索spring的官方文档,我发现可以通过注入SimpMessageHeaderAccessor在Controller方法中获取到那些值。

    /**
     * 交流
     * @param chatMessage
     */
    @MessageMapping("/chat")
    public void chat(SimpMessageHeaderAccessor headerAccessor, @RequestBody ChatMessage chatMessage) {
        User user = (User) headerAccessor.getSessionAttributes().get("user");  // right
        chatService.chat(user,chatMessage);
    }

这样我们便拿到了用户信息。

总结

本文说明了如何在Spring websocket中获取HttpSession,如果你使用了其他框架,也可以参考一下解决的思路,即在建立连接时保存session。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
WebSocket是一种协议,它允许在Web浏览器和Web服务器之间进行实时的双向通信。HTTPSession是一种在Web服务器和Web应用程序之间存储数据的机制。WebSocketHTTPSession都是Web应用程序常用的机制,但是它们的目的和用途不同。 WebSocket是一种协议,用于实现实时的双向通信。它允许在Web浏览器和Web服务器之间建立一个持久的连接,从而可以在两端之间发送实时数据。与HTTP请求不同,WebSocket连接是持久的,不需要每次请求都去建立一个新的连接。这使得WebSocket可以实现实时的双向通信,比如聊天室、在线游戏等应用。 HTTPSession是一种在Web服务器和Web应用程序之间存储数据的机制。它可以存储用户的会话信息,比如登录状态、购物车内容等。当用户在Web应用程序进行操作时,这些信息可以被存储在HTTPSession。Web应用程序可以随时从HTTPSession获取这些信息,从而实现用户状态的跟踪和管理。 在WebSocketHTTPSession可以用来存储与WebSocket连接相关的数据。比如,当一个用户与WebSocket建立连接时,可以将用户的会话信息存储在HTTPSession。当用户发送消息时,可以从HTTPSession获取用户的会话信息,从而实现消息的处理和分发。HTTPSession还可以用来存储WebSocket连接的状态信息,比如连接的当前状态、连接的过期时间等。 总之,WebSocketHTTPSession都是Web应用程序常用的机制,但它们的目的和用途不同。WebSocket用于实现实时的双向通信,HTTPSession用于存储和管理用户的会话信息。在WebSocketHTTPSession可以用来存储与WebSocket连接相关的数据和状态信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值