问题 Websocket - httpSession返回null


我想在websocket handshake \ session与HttpSession对象之间建立连接。

我使用了以下握手修改:

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator
{
@Override
public void modifyHandshake(ServerEndpointConfig config, 
                            HandshakeRequest request, 
                            HandshakeResponse response)
{
    HttpSession httpSession = (HttpSession)request.getHttpSession();
    config.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}

正如这篇文章中提到的: 从Web Socket @ServerEndpoint中的HttpServletRequest访问HttpSession

现在, 由于某些原因,握手时,(HttpSession)request.getHttpSession()始终返回null。

这是我的客户端代码:

<!DOCTYPE html>
<html>
<head>
<title>Testing websockets</title>
</head>
<body>
<div>
    <input type="submit" value="Start" onclick="start()" />
</div>
<div id="messages"></div>
<script type="text/javascript">
    var webSocket = 
        new WebSocket('ws://localhost:8080/com-byteslounge-websockets/websocket');

    webSocket.onerror = function(event) {
        onError(event)
    };

    webSocket.onopen = function(event) {
        onOpen(event)
    };

    webSocket.onmessage = function(event) {
        onMessage(event)
    };

    function onMessage(event) {
        document.getElementById('messages').innerHTML 
            += '<br />' + event.data;
    }

    function onOpen(event) {
        document.getElementById('messages').innerHTML 
            = 'Connection established';
    }

    function onError(event) {
        alert(event.data);
    }

    function start() {
        webSocket.send('hello');
        return false;
    }
</script>
</body>
</html>

为什么没有创建会话的任何想法? 谢谢


4873
2017-11-27 10:58


起源

我希望保留客户端代码 Servlet 要么 jsp 而不是普通的HTML可能会有所帮助,因为会话对象将在这些情况下启动。我没试过。 - Stalin Gino


答案:


这是预期的行为,但我同意这可能令人困惑。来自HandshakeRequest.getHttpSession的javadoc:

/**
 * Return a reference to the HttpSession that the web socket handshake that 
 * started this conversation was part of, if the implementation
 * is part of a Java EE web container.
 *
 * @return the http session or {@code null} if either the websocket
 * implementation is not part of a Java EE web container, or there is
 * no HttpSession associated with the opening handshake request.
 */

问题是,尚未为您的客户端连接创建HttpSession,而WebSocket API实现只是询问是否创建了某些内容,如果没有,则为 不创造它。你需要做的就是打电话 httpServletRequest.getSession() 某时 之前 调用WebSocket impl过滤器(doFilter(...) 叫做)。

这可以通过例如调用所提到的方法来实现 ServletRequestListener#requestInitalized 或在不同的过滤器等。


8
2017-11-29 14:33



如何从传递给requestInitalized方法的ServletRequestEvent pServletRequestEvent对象中获取httpservletRequest对象? - xMythicx


这是Pavel Bucek的答案的一个impl,在添加之后,我得到了我的会话

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;

@WebListener
public class RequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        // TODO Auto-generated method stub

    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        ((HttpServletRequest) sre.getServletRequest()).getSession();
    }

}

6
2017-12-16 20:35



由于我通常禁用Jar Scanning以加快启动速度,因此我不得不在web.xml中添加一个监听器,例如 <listener><listener-class>path.to.RequestListener</listener-class></listener> 为了注册 @WebListener 不依赖于注释。 - isapir


建立在 @ pavel-bucek的回答,我写了一篇 简单 HttpSessionInitializerFilter servlet过滤器

只需从“Releases”页面下载jar并将其保存在类路径中的任何位置,然后将以下代码段添加到web.xml描述符中(根据需要修改url-pattern):

<filter>
  <filter-name>HttpSessionInitializerFilter</filter-name>
  <filter-class>net.twentyonesolutions.servlet.filter.HttpSessionInitializerFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>HttpSessionInitializerFilter</filter-name>
  <url-pattern>/ws/*</url-pattern>
</filter-mapping>

0
2017-07-13 21:44





第一:创建一个新类

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;

@WebListener

public class RequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        ((HttpServletRequest)servletRequestEvent.getServletRequest()).getSession();
    }
}

然后在App main上添加“ServletComponentScan”注释:

@SpringBootApplication

@ServletComponentScan

public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

0
2017-08-25 03:17