Ответ 1
Сервлет HttpSession
находится в JSR-356, доступном HandshakeRequest#getHttpSession()
, который, в свою очередь, доступен, когда запрос на подтверждение приветствия выполняется до @OnOpen
@ServerEndpoint
. ServletContext
, в свою очередь, доступен только через HttpSession#getServletContext()
. Это две птицы с одним камнем.
Чтобы зафиксировать запрос подтверждения, выполните ServerEndpointConfig.Configurator
и переопределите modifyHandshake()
. HandshakeRequest
здесь доступен как аргумент метода. Вы можете поместить HttpSession
в EndpointConfig#getUserProperties()
. EndpointConfig
в свою очередь доступен как аргумент метода @OnOpen
.
Вот пример запуска реализации ServerEndpointConfig.Configurator
:
public class ServletAwareConfig extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
config.getUserProperties().put("httpSession", httpSession);
}
}
Здесь, как вы можете его использовать, обратите внимание на configurator
атрибут @ServerEndpoint
:
@ServerEndpoint(value="/your_socket", configurator=ServletAwareConfig.class)
public class YourSocket {
private EndpointConfig config;
@OnOpen
public void onOpen(Session websocketSession, EndpointConfig config) {
this.config = config;
}
@OnMessage
public void onMessage(String message) {
HttpSession httpSession = (HttpSession) config.getUserProperties().get("httpSession");
ServletContext servletContext = httpSession.getServletContext();
// ...
}
}
В качестве подсказки дизайна лучше всего поддерживать @ServerEndpoint
полностью без зависимостей API сервлета. Вы бы в реализации modifyHandshake()
лучше сразу извлекали именно эту информацию (обычно изменяемую Javabean), которая вам нужна из сеанса сервлетов или контекста, и вместо этого помещали их в карту свойств пользователя. Если вы этого не сделаете, то вам следует помнить, что сеанс websocket может жить дольше, чем сеанс HTTP. Поэтому, когда вы продолжаете переносить HttpSession
в конечную точку, вы можете столкнуться с IllegalStateException
при попытке получить к ней доступ, пока он истек.
Если у вас случайно есть CDI (и, возможно, JSF), вы можете получить вдохновение из исходного кода OmniFaces <o:socket>
(ссылки находятся на самом дне витрины).