【发布时间】:2023-03-14 06:22:01
【问题描述】:
我有一个自定义标签,它会进行一些处理,然后设置一个 cookie。但是,cookie 没有被设置,我不知道为什么。另一位开发人员指出,由于我们使用的是模板系统,即标签评估点,响应标头已经作为包含的一部分被刷新。由于标头已发送,因此似乎无法添加 cookie(但是,当我尝试这样做时,不会引发任何状态异常)。有没有解决的办法?这听起来像是问题所在吗?
【问题讨论】:
我有一个自定义标签,它会进行一些处理,然后设置一个 cookie。但是,cookie 没有被设置,我不知道为什么。另一位开发人员指出,由于我们使用的是模板系统,即标签评估点,响应标头已经作为包含的一部分被刷新。由于标头已发送,因此似乎无法添加 cookie(但是,当我尝试这样做时,不会引发任何状态异常)。有没有解决的办法?这听起来像是问题所在吗?
【问题讨论】:
就像其他人所说的那样,您确实希望一开始就避免这样做。您可能想要一个不错的 MVC 类型的模型,其中您有一些 servlet 来完成您的繁重工作,例如数据库和 cookie 等等,然后将控制权传递给实际呈现响应的 JSP。由于在您的 servlet 完成之前不会调用 JSP 来生成 HTML,因此您不应该像这样陷入困境。
当它失败时 setCookie 没有告诉你这有点蹩脚,但你可能不希望它破坏整个页面也是有道理的。 ServletResponse.isCommitted() 将告诉您标头是否已写入,因此您的 setCookie() 调用是否会失败。
如果您处于困境并且绝对需要能够做到这一点(当您寻找更好的解决方案时),您可以创建一个 servlet 过滤器来缓冲内存中的响应,直到设置 cookie 之后。模式是这样的:
doFilter(request, response, chain)
{
BufferedResponse bufferedResponse = new BufferedResponse(response);
try
{
// pass control to the next filter or to the JSP/servlet servicing the request
chain.doFilter(request, bufferedResponse);
}
finally
{
bufferedResponse.flush();
}
}
BufferedResponse 需要实现 HttpServletResponse 并基本上将所有内容保存在内存中,直到您明确刷新它为止。此时它会写出标头、cookie 和缓冲的响应正文。
这完全可行,但它会导致您的 Web 服务器使用大量额外的内存,因为它必须为每个请求在内存中缓冲整个响应体。此外,您的页面加载速度会变慢,因为在您的页面完全完成之前,服务器无法开始向客户端浏览器发送任何内容。坏juju我的朋友。
【讨论】:
嗯,HTTP cookie 是 HTTP 标头的一部分,所以这肯定是您的问题。因此,在刷新 HTTP 标头后,您根本无法编写 cookie。
您刷新而不使用响应缓冲的任何具体原因?或者,尝试确保在刷新之前修改标头并添加 cookie。
【讨论】:
我想一个可能的解决方法是发出 JavaScript 来设置 cookie。这种方法当然存在明显的问题。一个类似的技巧是包含一个 1x1 像素的 webbug,它会在加载时设置一个 cookie。
我建议让 JSP(和类似的)只关心创建页面视图。并且还保持很少的会话状态。
【讨论】:
HTTP 还知道在正文之后添加的页脚要像标题一样处理(相同格式)。不幸的是,HttpServletResponse 没有 addFooter 方法(例如,Resin API 有)。没有 api 会很困难。没有机会简单地将其添加到正文中 - 这将被解析为正文,而不是页脚。对不起。
如果您为浏览器编写 html,也许您可以在页面末尾(</html> 之前)包含一段 javascript 来设置 cookie。
【讨论】: