调用客户端重定向后,会话属性将丢失

以前,servlet使用response.sendRedirect("pages/my_page.jsp?foo=bar"); 没有问题。 可以在重定向到的后续页面中检索会话属性。

目前,我正在改变发送请求的方式。 最初,Javascript使用myForm.submit(); ,但我现在已将其更改为jQuery.ajax("my_page.jsp?foo=bar", {...}); 。 然后,servlet包含JSON响应中的URL而不是response.sendRedirect() ,并且在success函数中,我使用window.location.replace(url); 导航到新页面。 但是,无法在后续页面中获取已保存的会话属性。

我通过在JSP页面中插入来比较会话ID。 他们是一样的。 这里的问题是session.getAttribute("myAttribute_1")在重定向到的页面中返回null

我不确定这是否重要,但我实际上是在使用多个JSP页面执行此任务:

 A.jsp --- (redirect) ---> B.jsp --- (redirect) ---> C.jsp 

在这种情况下,如何在C.jsp获取保存的会话属性?


编辑

下面是我用来保存会话属性的代码片段。

 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(true); response.setContentType("application/json"); CustomObject customObject = new CustomObject(); // ... session.setAttribute("myAttribute_1", customObject); PrintWriter writer = response.getWriter(); JsonObject json = new JsonObject(); Gson gson = new GsonBuilder().setPrettyPrinting().create(); json.addProperty("url", "next_page.jsp?foo=bar"); writer.println(gson.toJson(json)); writer.close(); } 

以下是重定向的代码段。

 function redirectHandler(data, currentUrl) { if (data && data.hasOwnProperty('url')) { var redirectUrl = data.url; jQuery.get(redirectUrl).done(function(response) { redirectHandler(response, redirectUrl); }); } else { window.location.replace(currentUrl); } } function sendFormData(method, url, form) { jQuery.ajax(url, { 'method': method, 'data': parseData(jQuery(form).serializeArray()), 'success': function(data) { redirectHandler(data, window.location.href); } }); } 

结果

我已经恢复使用我的servlet中的response.sendRedirect("pages/my_page.jsp?foo=bar")

在客户端, jQuery.ajax()被删除,函数sendFormData()更新如下。

 function sendFormData(form) { var data = parseData(jQuery(form).serializeArray()); var f = document.createElement('form'); for (var key in data) { jQuery('').attr({ 'type': 'hidden', 'name': key, 'value': data[key] }).appendTo(f); } f.setAttribute('method', form.getAttribute('method')); f.setAttribute('action', form.getAttribute('action')); f.submit(); } 

每当我想提交表单时,都会附加一个click事件处理程序。 它将调用sendFormData(myOriginalForm); 而不是myOriginalForm.submit(); 因为我需要自定义要发送的数据。

只有应用这些简单的更改,一切都会再次起作用。

不过,我正在寻找关于这种奇怪行为的解释。

在服务器端

HTTP请求是无状态的,会话通过不同的方式放在HTTP之上

  • URL重写 (例如,服务器启动新会话并将其ID返回给客户端,然后客户端将会话ID附加到所有后续请求http://host:port/path;session_id=12345
  • cookie (例如,在会话创建服务器上使用cookie编码会话ID进行响应,并且在服务器端,您希望cookie将每个请求与现有会话相关联)。

客户有责任确保他们通过服务器预期的方式参与会话。 当使用Java Servlet API实现服务器时,它是jsessionid cookie或具有相同名称的查询参数附加到URL,后者标识会话ID。

如果客户端不支持cookie,则使用Java Servlet API,您将不得不重定向到由HttpServletResponse.encodeRedirectURL(String url)创建的HttpServletResponse.encodeRedirectURL(String url)

为了从servlet重定向,使用HttpServletResponse.sendRedirect(String url);

使用HTTP重定向标准对服务器进行响应将简化您的设计。 Jquery确实实现了这些标准,因此在这里将来自服务器的HTTP 301302响应,因此不需要客户端上的重定向逻辑。


在客户端

您的客户端是jquery ,当后续请求将发送到同一域时,其ajax实现将尊重并重放为任何给定域设置的cookie。

如果要重定向到其他域, 要使jqueryCORS会话一起使用,请将xhrFields到您的请求中:

 $.ajax({ url: a_cross_domain_url, xhrFields: { withCredentials: true } }); 

根据这个答案

您是否尝试过不同forms的Javascript重定向?

推荐的方法是:

 window.location.href=currentUrl; 

根据这篇文章 ,使用window.location.replace将替换当前会话。