Springboot中websocket获取httpsession存储webSocketSession

Websocket获取HttpSession过程
博客介绍了websocket获取HttpSession的过程,还提及下一篇将实现普通类中获取Httpsession以获取对应的websocket Session,聚焦于信息技术领域的Websocket相关操作。
WebsocketConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

@Configuration
public class WebSocketConfig extends ServerEndpointConfig.Configurator{

    /* 修改握手,就是在握手协议建立之前修改其中携带的内容 */
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession = (HttpSession)request.getHttpSession();
        if (httpSession != null) {
            // 读取session域中存储的数据
            sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
        }
        super.modifyHandshake(sec, request, response);
    }

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
WebsocketListener.java

import org.springframework.stereotype.Component;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Component
public class WebsocketListener implements ServletRequestListener{
    @Override
    public void requestInitialized(ServletRequestEvent sre)  {
        HttpSession session = ((HttpServletRequest) sre.getServletRequest()).getSession();
    }

    public WebsocketListener(){}

    @Override
    public void requestDestroyed(ServletRequestEvent arg0)  {}
}
Websocket.java

import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.*;

@ServerEndpoint(value = "/websocket",configurator = WebSocketConfig.class)
@Component
public class WebSocket {

    private Session session;

    @OnOpen
    public void onOpen(Session session,EndpointConfig config){
        HaigeSatContext.getInstance().getOnlineWebSocketSessions().add(session);
        System.out.println("-------------websocket open--------------");
        HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        String httpSessionId = httpSession.getId();
        System.out.println("httpSessionId:"+httpSessionId);
        //此处省略使用sessionId构建hashMap集合存储websocket Session

    }

    @OnClose
    public void onClose(Session session){
        System.out.println("-------------websocket close--------------");
    }

    @OnMessage
    public void OnMessage(String message, Session session){
        System.out.println("-------------recv message--------------");
        System.out.println("message:"+message);

    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("---------------websocket error-------------------------");
    }

}

以上即为websocket获取HttpSession过程,下一篇实现普通类中获取Httpsession来获取对应的websocket Session。

<think>好的,我现在需要帮助用户在Spring Boot中通过WebSocketSession获取URL中的传入参数。首先,我得回忆一下WebSocket在Spring中的处理流程。通常,WebSocket连接建立时,客户端会发送一个HTTP请求进行握手,这个请求的URL可能包含查询参数。用户的问题是如何在服务端获取这些参数。 我记得在Spring WebSocket中,可以通过HandshakeInterceptor来拦截握手请求,这样就能获取到HTTP请求的信息。或者,可能在建立连接的时候,WebSocketSession中已经包含了这些信息?需要仔细查看WebSocketSession的API文档。 WebSocketSession有一个getUri()方法,可以获取到建立连接时的URI。这个URI应该包含了客户端请求的完整路径和参数。例如,如果客户端连接的是ws://example.com/endpoint?param=value,那么getUri()会返回对应的URI对象。然后,可以通过URI对象的getQuery()方法获取查询字符串,再解析参数。 不过,解析查询字符串可能需要手动处理,或者使用Spring的工具类。例如,UriComponentsBuilder可以帮助解析URI中的参数。比如,使用UriComponentsBuilder.fromUri(session.getUri()).build().getQueryParams()来获取参数映射。 另外,可能还需要考虑在WebSocket的@OnOpen方法中如何访问这些参数。在Spring中,可能需要在拦截器中将参数保存到WebSocketSession的属性中,然后在处理连接时从session中获取这些属性。 例如,在HandshakeInterceptor的beforeHandshake方法中,可以从request参数中获取查询参数,并将其放入attributes中。这样,在建立WebSocket连接后,可以通过WebSocketSession的getAttributes()方法获取这些参数。 还需要考虑路径参数和查询参数的区别。用户提到的是URL中的参数,通常是查询参数,即?后面的部分。如果是路径参数,处理方式可能不同,但用户的问题应该是针对查询参数。 另外,注意WebSocket的协议升级过程,握手阶段的请求参数只能在握手阶段获取,之后在WebSocket协议中不能再直接访问HTTP请求的参数,所以必须通过拦截器在握手阶段保存这些参数。 总结一下,步骤可能是: 1. 创建一个实现HandshakeInterceptor的拦截器类。 2. 在beforeHandshake方法中,从HttpServletRequest获取查询参数。 3. 将参数存入attributes中。 4. 在WebSocket处理器中,通过WebSocketSession的getAttributes()获取这些参数。 或者,如果不需要拦截器,直接在WebSocketSession中解析URI中的查询参数。 现在,需要验证这个思路是否正确。例如,在WebSocketHandler中,当连接建立时,可以通过session.getUri()获取URI,然后解析查询参数。例如: URI uri = session.getUri(); String query = uri.getQuery(); 然后,将query字符串拆解成键值对,或者使用UriComponentsBuilder来解析。 例如: Map<String, String> queryParams = UriComponentsBuilder.fromUri(uri).build().getQueryParams().toSingleValueMap(); 不过,可能需要处理多个同名参数的情况,但通常查询参数是单个值,这里用户可能需要的是获取特定参数的值。 所以,用户的问题可以通过这两种方式解决:使用拦截器保存参数到session属性,或者在连接建立时解析URI中的查询参数。 接下来,需要给出具体的代码示例,展示这两种方法。 第一种方法,使用HandshakeInterceptor: public class MyHandshakeInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpServletRequest httpServletRequest = servletRequest.getServletRequest(); String paramValue = httpServletRequest.getParameter("paramName"); attributes.put("paramName", paramValue); } return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } } 然后在配置中注册这个拦截器: @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/endpoint").addInterceptors(new MyHandshakeInterceptor()); } @Bean public WebSocketHandler myHandler() { return new MyWebSocketHandler(); } } 然后在WebSocketHandler中,可以通过session.getAttributes().get("paramName")获取参数。 第二种方法,直接在WebSocketHandler中解析URI: public class MyWebSocketHandler extends TextWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { URI uri = session.getUri(); String query = uri.getQuery(); // 解析查询参数 Map<String, String> params = parseQuery(query); String paramValue = params.get("paramName"); // 使用参数... } private Map<String, String> parseQuery(String query) { if (query == null) return Collections.emptyMap(); return Arrays.stream(query.split("&")) .map(pair -> pair.split("=")) .collect(Collectors.toMap( arr -> URLDecoder.decode(arr[0], StandardCharsets.UTF_8), arr -> URLDecoder.decode(arr.length > 1 ? arr[1] : "", StandardCharsets.UTF_8))); } } 或者使用Spring的UriComponentsBuilder: UriComponents components = UriComponentsBuilder.fromUri(uri).build(); String paramValue = components.getQueryParams().getFirst("paramName"); 这种方法不需要拦截器,直接处理即可。 两种方法各有优劣。拦截器方式可能更灵活,可以在握手阶段处理更多逻辑,而直接解析URI则更简单。 需要提醒用户注意URL编码的问题,比如参数值中的特殊字符会被编码,需要解码。例如,使用URLDecoder.decode()来处理。 另外,如果在拦截器中获取参数,需要注意ServletServerHttpRequest的转换是否安全,是否存在其他类型的ServerHttpRequest实现,可能需要做类型检查。 现在,编写具体的步骤和示例代码,确保用户能够理解并实施这两种方法。</think>在Spring Boot中通过WebSocketSession获取URL参数,可通过以下两种方法实现: --- ### 方法一:使用HandshakeInterceptor拦截器 1. **创建拦截器类**:实现`HandshakeInterceptor`接口,在握手阶段提取参数 ```java public class ParamInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; String token = servletRequest.getServletRequest().getParameter("token"); attributes.put("token", token); // 参数存入会话属性 } return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {} } ``` 2. **注册拦截器** ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/ws") .addInterceptors(new ParamInterceptor()); } @Bean public WebSocketHandler myHandler() { return new MyHandler(); } } ``` 3. **在处理器中获取参数** ```java public class MyHandler extends TextWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) { String token = (String) session.getAttributes().get("token"); // 使用参数进行业务处理 } } ``` --- ### 方法二:直接解析URI查询字符串 1. **在WebSocket处理器中解析URI** ```java public class UriParamHandler extends TextWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) { URI uri = session.getUri(); MultiValueMap<String, String> params = UriComponentsBuilder .fromUri(uri) .build() .getQueryParams(); String userId = params.getFirst("userId"); // 获取参数值 } } ``` --- ### 关键区别说明 | 方法 | 优点 | 适用场景 | |------|------|----------| | 拦截器 | 可获取完整HTTP请求对象,支持复杂逻辑处理 | 需要访问Cookie/Header等额外信息时[^1] | | URI解析 | 实现更简洁,无拦截器注册步骤 | 仅需处理简单查询参数时 | --- ### 参数编码注意事项 若参数包含特殊字符(如空格、中文),需进行URL编解码: ```java String decodedValue = URLDecoder.decode(rawValue, StandardCharsets.UTF_8); ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值