【发布时间】:2014-05-13 04:34:22
【问题描述】:
在 Websocket 和 Rest 服务之间共享 HttpSession 有一个很好的例子。 (Spring DispatchServlet cannot find resource within Jetty) 但这对我不起作用。我不确定我是否缺少任何东西?
我使用 Jetty 作为 websocket 服务器,还创建了一个由 SpringConfig 注入的 WebApp。
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;Version=1;Path=/rs;Secure]
事情看起来很完美。
最后,创建一个服务端ServerEndpointConfigurator类,重写modifyHandshake()方法来获取session和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"
有人知道是什么原因吗?
【问题讨论】:
标签: rest session websocket share endpoint