Websocket - httpSession возвращает ноль

Я хотел бы установить связь между рукопожатием \ сеансом веб-сокета с объектом 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);
}
}

Как упоминалось в этом сообщении: Доступ к HttpSession из HttpServletRequest в веб-сокете @Конечная точка сервера

Теперь по какой-то причине при рукопожатии (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>

Любые идеи, почему сеанс не создается? Спасибо


person Urbanleg    schedule 27.11.2013    source источник
comment
Я надеюсь, что сохранение кода на стороне клиента в Servlet или jsp вместо простого html может помочь, поскольку в этих случаях будет инициирован объект сеанса. Хотя я не пробовал.   -  person Stalin Gino    schedule 13.12.2014


Ответы (4)


Это предполагаемое поведение, но я согласен, что это может сбивать с толку. Из javadoc HandshakeRequest.getHttpSession:

/**
 * 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 (вызывается doFilter(...)).

Этого можно добиться, например, вызвав указанный метод в ServletRequestListener#requestInitalized или в другом фильтре и т. д.

person Pavel Bucek    schedule 29.11.2013
comment
Как получить объект httpservletRequest из объекта ServletRequestEvent pServletRequestEvent, переданного методу requestInitalized? - person xMythicx; 03.09.2015

Вот импл для ответа Павла Бучека, после его добавления я получил свою сессию

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();
    }

}
person wutzebaer    schedule 16.12.2015
comment
Поскольку я обычно отключаю сканирование Jar для более быстрого запуска, мне также пришлось добавить прослушиватель в web.xml, например. <listener><listener-class>path.to.RequestListener</listener-class></listener>, чтобы зарегистрировать @WebListener, не полагаясь на аннотации. - person isapir; 22.09.2016

Основываясь на @pavel-bucek answer, я написал простой HttpSessionInitializerFilter фильтр сервлетов.

Просто загрузите банку со страницы «Релизы» и сохраните ее в любом месте пути к классам, затем добавьте следующий фрагмент в свой дескриптор web.xml (при необходимости измените шаблон URL):

<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>
person isapir    schedule 13.07.2017

первый: создать новый класс

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();
    }
}

а затем добавьте аннотацию «ServletComponentScan» в основное приложение:

@SpringBootApplication

@ServletComponentScan

public class Application {

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