Websocket - httpSession возвращает null
Я хотел бы установить связь между рукопожатием websocket\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);
}
}
Как упоминалось в этом сообщении:
Доступ к HttpSession из HttpServletRequest в веб-Socket @ServerEndpoint
Теперь,
По какой-то причине при дрожании руки (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>
Любые идеи, почему сеанс не создается?
Благодаря
Ответы
Ответ 1
Это предполагаемое поведение, но я согласен, что это может ввести в заблуждение. Из файла 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 еще не создан для вашего клиентского соединения, а реализация API WebSocket просто спрашивает, есть ли что-то, созданное, а если нет, то не создает его. Что вам нужно сделать, это вызвать httpServletRequest.getSession()
sometime до Вызывается фильтр implos WebSocket (вызывается doFilter(...)
).
Это может быть достигнуто, например, путем вызова упомянутого метода в ServletRequestListener#requestInitalized
или в другом фильтре и т.д.
Ответ 2
Вот для Павла Бучека ответ, после добавления его, я получил свою сессию
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();
}
}
Ответ 3
Основываясь на @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>
Ответ 4
сначала: создать новый класс
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);
}
}