简体   繁体   English

JSF 2.0:AJAX调用后,cookie不会立即保留,需要HTTP请求

[英]JSF 2.0: cookies are not persisted immediately after AJAX call, HTTP request required

Ajax call performed in order to remove item from shopping cart - removeOrder() method is called 为了从购物车中删除商品而执行的Ajax调用- removeOrder()方法

UI removeOrder() call(JSF&Primefaces): UI removeOrder()调用(JSF&Primefaces):

<p:commandButton value="clean" actionListener="#{showProducts.removeOrder}"
   process="@form" update="@form,:ccId:cCart:ccSizeId,:ccId:cCart:ccTotId" immediate="true">
<f:attribute name="remove" value="#{cart.name}"/>
</p:commandButton>

Backend removeOrder() call(managed bean) 后端removeOrder()调用(托管Bean)

public void removeOrder(ActionEvent e) {
        String productName = (String) e.getComponent().getAttributes().get("remove");
        Product p = getProductByName(productName);
        inCart.remove(p);
        persistCookies();
        emptyCartNotifier();
        totalRendered();
    }

Here cookies is persisted,output of this method as is expected,Cookie array contains cookies with empty values,that's OK: 这是cookie的持久性,按预期输出此方法,Cookie数组包含具有空值的cookie,可以:

private void persistCookies() {
    HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();

    String ids = "";

    for (Product prod : inCart) {
        // TODO change logic to support real count,for now 1 is available only
        ids += prod.getId() + ";" + prod.getCount() + "_";
    }

    Cookie cookie = new Cookie(SC_COOKIE, ids);
    Cookie cookie2 = new Cookie(SC_SIZE, String.valueOf(inCart.size()));
    Cookie cookie3 = new Cookie(SC_TOTAL_PRICE, String.valueOf(subTotal));
    cookie3.setPath("/");
    cookie3.setMaxAge(TWO_WEEKS);
    httpServletResponse.addCookie(cookie3);
    cookie.setPath("/");
    cookie.setMaxAge(TWO_WEEKS);
    cookie2.setPath("/");
    cookie2.setMaxAge(TWO_WEEKS);

    httpServletResponse.addCookie(cookie);
    httpServletResponse.addCookie(cookie2);

}

Here problem occurred, the method emptyCartNotifier() see non-empty "previous" Cookies array 发生问题后,方法emptyCartNotifier()看到非空的“上一个” Cookies数组

private String emptyCartNotifier() {

    HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    Cookie[] cookies = httpServletRequest.getCookies();
    boolean isCookiePresent = false;
    if (cookies != null) {
        for (Cookie c : cookies) {
            if (SC_COOKIE.equals(c.getName()) && (!c.getValue().isEmpty())) {
                isCookiePresent = true;
            }
        }
    }
    if (inCart.isEmpty() && (!isCookiePresent)) {
        emptyCartNotifier = "you cart is empty";
        isFormRendered = false;
    } else {
        emptyCartNotifier = "";
        isFormRendered = true;
    }
    return emptyCartNotifier;
}

After any HTTP request performed, that Cookie array is really cleaned up. 在执行任何HTTP请求之后,该Cookie数组才真正被清除。

As I see , clash is: 如我所见,冲突是:
after AJAX call cleans cookie, that HttpServletRequest contains non-empty cookie until new HTTP request performed(user submit button or go by link). 在AJAX调用清除cookie后,该HttpServletRequest包含非空cookie,直到执行新的HTTP请求(用户提交按钮或按链接转到)为止。

Is there solution or good practice for immediate cookie management,when web-app combines AJAX and non-AJAX calls? 当网络应用程序结合使用AJAX和非AJAX调用时,是否存在用于即时Cookie管理的解决方案或良好做法?

Thank you. 谢谢。

Your cookie problem is one thing, but I think there is a much easier way to get things done. Cookie的问题是一回事,但我认为有一种更轻松的方法来完成任务。

In your page, just replace the pages you mention with this: 在您的页面中,只需用以下内容替换您提到的页面:

<p:commandButton value="clean" action="#{showProducts.removeOrder(cart)}"
   process="@form" update="@form,:ccId:cCart:ccSizeId,:ccId:cCart:ccTotId" immediate="true" />

Backing bean (eg session scoped): 支持bean(例如,会话作用域):

private double subtotal; // don't forget getter and setter

public void removeOrder(Product product) {
        inCart.remove(product);
        // calculate subtotal
}

I guess you show the subtotal and maybe list all products after calling removeOrder . 我猜您显示了小计,也许在调用removeOrder之后列出了所有产品。 Just recalculate subtotal after removing the product, and make sure the shopping cart is refreshed ( update attribute). 删除产品后,只需重新计算小计,并确保购物车已刷新( 更新属性)。

This code is simple enough and easy to understand, and yet does everything you need. 这段代码非常简单易懂,却可以满足您的所有需求。 No need to "manually" manage cookies. 无需“手动”管理cookie。

You could try setting your cookies setHttpOnly(true) , but the question is why would you need "ajax-scoped" cookie persistence at all? 您可以尝试将cookie设置为setHttpOnly(true) ,但问题是,为什么根本需要“ ajax范围的” cookie持久性?

Why not use local variables in your view/request/session scoped beans? 为什么不在视图/请求/会话范围的bean中使用局部变量? They're actually designed for that sort of tasks. 它们实际上是为这类任务而设计的。 If you want additional cookie persistence you do it in corresponding setters or action methods. 如果您希望获得额外的cookie持久性,则可以使用相应的setter或action方法进行。

Wait, what? 等一下 In emptyCartNotifier , You are calling getCookies on the HttpRequest object, which is supposed to contain the cookies that were in the HTTP request that triggered your method, so of course you don't see changes until the next request. emptyCartNotifier ,您正在HttpRequest对象上调用getCookies ,该对象应该包含触发您的方法的HTTP请求中的cookie,因此,当然,在下一个请求之前,您不会看到更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM