有一个在Websocket和Rest服务之间共享HttpSession的好例子。(Spring DispatchServlet无法在Jetty中找到资源)但它不适合我。我不确定我是不是漏掉了什么?
我使用Jetty作为websocket服务器,我还创建了一个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并存储了一些东西。如我所说,它有效,会话也有效。
Rest客户端:
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; Version = 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已经被改变了:
有谁知道原因是什么吗?饼干:JSESSIONID ="tvum36z6j2bc1p9uf2gumxguh";$路径= "/rs "
好吧,我明白了,这是因为我把WebSocket和Rest到不同的上下文处理程序。Jetty使处理程序彼此隔离。要共享会话信息,必须将它们放在一起。
但是如果有人想要分离它们,仍然可以通过共享SessionManager或SessionHandler来完成。有许多方法可以实现这一点,您可以将SessionHandler注入到每个ServletContext中,或者只是将其定义为一个静态变量,并将其放在每个人都可以到达的地方,每种方法都有效。