Почему HandshakeRequest не возвращает HttpSession в моем ServerEndpointConfig.Configurator?

Есть хороший пример совместного использования HttpSession между Websocket и сервисом Rest. (Spring DispatchServlet не может найти ресурс в Jetty) Но это не так. работай на меня. Я не уверен, есть ли что-то, что мне не хватает?

Я использую Jetty в качестве сервера веб-сокетов, а также создал WebApp, который вводится SpringConfig.

private void init() throws Exception
{
    Server server = new Server();

    // Create SSL Connector
    ServerConnector serverConnector = getSSLConnector(server);

    // Bundle to server
    server.setConnectors(new Connector[] { serverConnector });

    // Create request handler collection
    HandlerCollection handlers = new HandlerCollection();


    // Add WebSocket handler
    final ServletContextHandler servletContextHandler = getWebSocketContextHandler();
    handlers.addHandler(servletContextHandler);

    // Add Servlet handler
    handlers.addHandler(getWebAppServletContextHandler());


    server.setHandler(handlers);
    // Initial WebSocket
    WebSocketServerContainerInitializer.configureContext(servletContextHandler);

    // Start Jetty
    server.start();
    server.join();
}

И WebSocket, и Rest отлично работают с одним и тем же портом, конечно, с разными путями контекста.

Теперь я создал службу Rest:

@RequestMapping(value = "/login", method = RequestMethod.POST)
@Consumes({ MediaType.APPLICATION_JSON_VALUE })
@Produces({ MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody Message login(@RequestBody Credential credential, @Context HttpServletRequest servlerRequest) 
{
    ...
    HttpSession session = servlerRequest.getSession(true);
    session.setAttribute("userName", credential.getUserName());
    ...
    Message message = new Message();
    ...
    return message;
}

В этом сервисе я создал HttpSession и что-то сохранил. Как я уже сказал, он работает, и сеанс тоже.

Отдых клиент:

public void login() throws KeyManagementException, NoSuchAlgorithmException
{
    final String loginServiceUri = HTTP_SERVICE_BASE_URI + "/login";

    ClientConfig clientConfig = new DefaultClientConfig();
    ...

    Client client = Client.create(clientConfig);
    WebResource webResource = client.resource(loginServiceUri);
    ClientResponse response = webResource
            .type("application/json")
            .post(ClientResponse.class, new Credential("user","pass"));

    if (response.getStatus() != 200) {
        throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
    }

    List<NewCookie>cookies = response.getCookies();
    ClientEndpointConfigurator.setCookies(cookies);     <== Store cookies as well as session to ClientEndpointConfigrator class

    Message message = response.getEntity(Message.class);
    ...
}

Класс ClientEndpointConfigrator имеет статический список для всех файлов cookie, которые похожи на это:

public class ClientEndpointConfigurator extends ClientEndpointConfig.Configurator {
    private static List<NewCookie> cookies = null;
    public static void setCookies(List<NewCookie> cookies) {
        ClientEndpointConfigurator.cookies = cookies;
    }
    ...
    @Override
    public void beforeRequest(Map<String, List<String>> headers) {
        ...
        if(null != cookies)
        {
            List<String> cookieList = new ArrayList<String>();
            for(NewCookie cookie: cookies)
            {
                cookieList.add(cookie.toString());
            }
            headers.put("Cookie", cookieList);
        }
        ...
    }
}

Метод beforeRequest() поместит все файлы cookie в заголовок запроса. Если вы проверите cookieList, вы увидите:

[JSESSIONID=tvum36z6j2bc1p9uf2gumxguh;Версия=1;Путь=/rs;Безопасный]

Вещи выглядят идеально.

Наконец, создайте серверный класс ServerEndpointConfigurator и переопределите методmodifyHandshake() для получения сеанса и файлов cookie.

public class SpringServerEndpointConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        super.modifyHandshake(sec, request, response);
        httpSession = (HttpSession)request.getHttpSession();    <== **It returns null here!**
        ...

        }
    }
}

Я не могу вернуть свой HttpSession! и если вы распечатаете заголовки, вы увидите, что файл cookie был изменен:

Файл cookie: JSESSIONID="tvum36z6j2bc1p9uf2gumxguh";$Path="/rs"

Кто-нибудь знает, в чем причина?


person user3593261    schedule 13.05.2014    source источник


Ответы (1)


Хорошо, я понял это, потому что я поместил WebSocket и Rest в другой обработчик контекста. Jetty изолирует обработчиков друг от друга. Чтобы поделиться информацией о сеансе, вы должны собрать их вместе.

Но если кто-то хочет их разделить, это все же можно сделать, поделившись SessionManager или SessionHandler. Есть много способов добиться этого, вы можете внедрить SessionHandler в каждый ServletContext или просто определить его как статическую переменную и поместить туда, куда каждый может добраться, каждый способ работает.

person user3593261    schedule 14.05.2014