【问题标题】:Not able to add more than 2 values in cookies无法在 cookie 中添加超过 2 个值
【发布时间】:2018-06-05 15:35:12
【问题描述】:

您好,我是 java servlet 的新手。我试图使用 cookie 实现简单的购物车问题。在我的网页中,我要求用户输入可以添加到购物车的产品名称。

网页: 简单文本输入(产品名称) 和一个按钮(添加到购物车)

点击按钮后,网页会显示购物车值。

我遇到了一个奇怪的问题。它适用于少于 3 个值。当我尝试添加第三个值时,它只显示最近添加的两个值。例如,如果我分别添加产品 a、b 和 c。它只显示 b 和 c。

购物车 Servlet 代码:

String name = request.getParameter("productname");

Cookie cookie = new Cookie("product", name);
cookie.setMaxAge(100 * 60);     
response.addCookie(cookie);


Cookie[] cookies = request.getCookies();

List<String> names = new ArrayList<String>();
names.add(name);

if (cookies != null) {
    for (Cookie c: cookies) {
        if (c.getName().equals("product")) {
            names.add(c.getValue());
        }
    }
}

PrintWriter writer = response.getWriter();
for (String item: names) {
    writer.println("<h4>" + item + "</h4>");
}

index.jsp:

<form method="post" action="Cart">
 <input type="text" name="productname" value="Product name">
 <input type="submit" value="AddToCart">
</form>

我花了很多时间来弄清楚其中有什么问题。但我找不到任何错误来解释这种奇怪的行为。请帮忙。

【问题讨论】:

    标签: http servlets cookies


    【解决方案1】:

    该行为来自您的客户端(浏览器)和服务器处理同名 cookie 的方式。

    "多个cookie可能具有相同的名称但不同的路径 属性。”

    https://docs.oracle.com/javaee/7/api/javax/servlet/http/Cookie.html

    所以在您的情况下,它基本上是不断更新的相同 cookie(基于名称和路径)。

    那么在您的情况下会发生什么:基本上,浏览器通过向 HTTP 请求标头添加字段来将 cookie 返回到 servlet。假设您的第一个产品名为 a,而您发送的第二个产品的名称为 b,您的 cookie-header 看起来像

    Cookie:JSESSIONID=BCC7050AE82AEA1A4B9BED1174424A92; product=a
    

    和你的表单数据

    productname:b
    

    服务器接收到请求并创建一个新的Cookie 并将其添加到HttpResponse cookie 列表中。包含两个名为 product 的 cookie 的列表已正确打印在您的响应中。由于 servlet 使用 HTTP 响应标头将 cookie 发送到浏览器,并且您的 cookie 是相同的,因此只会进行更新。

    Set-Cookie:product=b; Expires=Sat, 23-Dec-2017 11:23:53 GMT 
    

    因此,下一个请求仅包含有关产品b 的信息,而产品a 消失了。

    【讨论】:

    • @f1I2 这是否意味着每次将产品添加到购物车时我都应该为 cookie 使用不同的名称?
    • 其实我很想知道网站是如何实现购物车的?如果我使用 http 会话,一旦浏览器关闭,它们就会丢失。这就是为什么我使用 cookie 以便它们可以停留更长时间。但是对于 cookie,存在容量问题,oracle 文档说每个 Web 服务器只支持 20 个 cookie。这意味着它是一种非常宝贵的资源。
    • @assasinC 会话本身由 cookie 标识,默认情况下,只要浏览器打开,该 cookie 就会存在。您基本上想要一个会话 cookie,它的寿命比这个默认的长。这个article 描述了如何做到这一点。
    • 这正是我在文章中所说的。我正在使用 cookie api 并添加到响应中,然后从请求中获取 cookie。但这里的问题是,我应该如何使用 cookie 来添加多个购物车项目。因为如果我保持相同的名称,它会被现有的名称替换,但是如果我为每个购物车项目命名不同的名称,那么很快 cookie 就会用尽。我能看到的一种方法是将它放在一个分隔的字符串中。这样每次我在购物车中添加新商品时,我只需将其 id 附加到现有的 cookie 值。
    • 在我之前的评论中,我试图解释 HttpSession (docs.oracle.com/javaee/7/api/javax/servlet/http/…) 如何与 session cookie 一起工作。在我看来,HttpSession 是您用例的正确选择。 HttpSessions 有一个唯一的标识符,将它们映射到特定的用户。此标识符可以在 URL 中传递或保存到特定的 session cookie 中,默认情况下,一旦浏览器关闭,session cookie 和 HttpSession 就会丢失,但您可以更改这个setting
    【解决方案2】:

    我发现 web.xml 中的以下部分即使在关闭浏览器后也不会使会话无效。感谢fI12推荐Session Lost when closing the browser的链接。

    <session-config>
       <session-timeout>11520</session-timeout>
       <cookie-config>
         <max-age>11520</max-age>
       </cookie-config>
    </session-config>
    

    将 cookie 用于购物车并不是一个可扩展的解决方案。会话就是这种方式。

    【讨论】:

      猜你喜欢
      • 2014-12-24
      • 2020-02-14
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多