使用@Push读写cookie

时间:2015-01-22 10:15:24

标签: vaadin vaadin7

在我的vaadin应用程序中,我需要使用@Push,但由于我添加了它,我无法读取和写入cookie,因为VaadinService.getSurrentResponse()Push而返回null。我使用这个类来管理cookie:

import javax.servlet.http.Cookie;

import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinService;

public class CookieManager {
    private VaadinResponse response;

    public CookieManager(VaadinResponse response){
        this.response = response;
    }

    public Cookie getCookieByName(final String name) {
        // Fetch all cookies from the request
        Cookie[] cookies = VaadinService.getCurrentRequest().getCookies();

        // Iterate to find cookie by its name
        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                return cookie;
            }
        }
        return null;
    }

    public Cookie createCookie(final String name, final String value, final int maxAge) {
        // Create a new cookie
        final Cookie cookie = new Cookie(name, value);

        cookie.setMaxAge(maxAge);

        // Set the cookie path.
        cookie.setPath(VaadinService.getCurrentRequest().getContextPath());

        // Save cookie
        addCookie(cookie);          

        return cookie;
    }

    private void addCookie(Cookie cookie){
        response.addCookie(cookie);
    }

    public Cookie updateCookieValue(final String name, final String value) {
        // Create a new cookie
        Cookie cookie = getCookieByName(name);

        cookie.setValue(value);

        // Save cookie
        addCookie(cookie);

        return cookie;
    }

    public void destroyCookieByName(final String name) {
        Cookie cookie = getCookieByName(name);

        if (cookie != null) {
            cookie.setValue(null);
            // By setting the cookie maxAge to 0 it will deleted immediately
            cookie.setMaxAge(0);
            cookie.setPath(VaadinService.getCurrentRequest().getContextPath());
            addCookie(cookie);
        }
    }
}

当我想创建一个cookie时(比如在用户的登录时),由于VaadinResponse为空,我得到一个nullPointerException。

所以我尝试禁用Push in构造函数并在addCookie()方法结束时重新启用它,但它禁用了对我的所有应用程序的推送,即使我在{{1}之后重新启用它}}方法。

我在vaadin的trac(http://dev.vaadin.com/ticket/11808)上看到了一张票,说不会修复,有人建议从服务器创建一个常规的AJAX查询来创建cookie,但我真的不喜欢这样做。我知道怎么做。

如何管理我的Cookie?我需要创建并获取Cookie,因此javascript无法帮助我,因为我无法通过vaadin获得javascript返回,因此我无法获取Cookie。

3 个答案:

答案 0 :(得分:3)

以下是我在@Push使用时如何存储cookie的解决方案。 首先,我们创建容器来存储客户端UI的所有实例。 ( 这个容器本身有很大的潜力)

public class UISession {

private List<WebAppUI> uis = new ArrayList<WebAppUI>();

public void addUI(WebAppUI webAppUI) {
    uis.add(webAppUI);
}

public List<WebAppUI> getUIs() {
    return uis;
}

public static UISession getInstance() {
    try {
        UI.getCurrent().getSession().lock();
        return (UISession) UI.getCurrent().getSession().getAttribute("userUiSession");
    } finally {
        UI.getCurrent().getSession().unlock();
    }
}

在UI.init()中,我们向会话添加新实例(例如,当用户打开新选项卡时)

@Override
protected void init(VaadinRequest vaadinRequest) {
    /** Set singleton uisesison for each browser*/
    if(UISession.getInstance()==null){
        UI.getCurrent().getSession().setAttribute("userUiSession",new UISession());
    }
    UISession.getInstance().addUI(this);
    System.out.println("UI count fo current browser "+UISession.getInstance().getUIs().size());
    ... 
}

这是我的助手cookie类:

class MyCookie{
private String value;
private String name;
private Date expired;
private String path="/";

public MyCookie(String name, String value) {
    this.name=name;
    this.value=value;
}
public void setMaxAge(int minute) {
    Calendar c = Calendar.getInstance();
    c.add(Calendar.MINUTE, minute);
    expired=c.getTime();

}
public String getStringToCreateCookie(){
    return "document.cookie=\""+getName()+"="+getValue()+"; expires="+expired.toString()+"; path="+path+"\"";
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getValue() {
    return value;
}
public void setValue(String value) {
    this.value = value;
}
public Date getExpired() {
    return expired;
}
public void setExpired(Date expired) {
    this.expired = expired;
}
public String getPath() {
    return path;
}
public void setPath(String path) {
    this.path = path;
}

}

在最后我们需要添加新cookie时,我们必须找到活跃的Ui并调用js函数

public static void addCookie(String name, String value, int age){
    MyCookie myCookie = new MyCookie(name, value);
    myCookie.setMaxAge(age);
    for(WebAppUI ui : UISession.getInstance().getUIs()){
        if(ui.isAttached()){
            ui.getPage().getJavaScript().execute(myCookie.getStringToCreateCookie());
            return;
        }
    }
}

在我的情况下,我可以访问存储cookie(当用户提出请求时)。我只是在添加新cookie时遇到问题,所以这是我的工作解决方案。

答案 1 :(得分:0)

如上所述in the ticket,您可以使用JavaScript来调用客户端代码,并通过该代码请求cookie值。 E.g。

@Grapes([
        @Grab('org.vaadin.spring:spring-boot-vaadin:0.0.3'),
        @Grab('com.vaadin:vaadin-server:7.4.0.beta1'),
        @Grab('com.vaadin:vaadin-client-compiled:7.4.0.beta1'),
        @Grab('com.vaadin:vaadin-themes:7.4.0.beta1'),
        ])
import com.vaadin.ui.*

@org.vaadin.spring.VaadinUI
@groovy.transform.CompileStatic
class MyUI extends UI {

    protected void init(com.vaadin.server.VaadinRequest request) {
        final resultLabel = new Label()
        // provide a callback for the client to tell the cookies
        JavaScript.current.addFunction("tellCookie", { elemental.json.JsonArray arguments ->
            resultLabel.value = arguments?.get(0)?.asString()
        } as JavaScriptFunction)
        setContent(new VerticalLayout().with{
            addComponent(new Button("Set Cookie", {
                // just simply set the cookies via JS (attn: quoting etc)
                JavaScript.current.execute("document.cookie='mycookie=${System.currentTimeMillis()}'")
            } as Button.ClickListener))
            addComponent(new Button("Get Cookie", {
                // tell the client to tell the server the cookies
                JavaScript.current.execute("this.tellCookie(document.cookie)")
            } as Button.ClickListener))
            addComponent(resultLabel)
            return it
        })
    }
}

这是一个用于测试的运行示例(例如spring run vaadin.groovy)。请参阅重要部分的注释。

答案 2 :(得分:0)

The Viritin add-on包含一个名为BrowserCookie的帮助器类。它的工作方式几乎与cfrick建议的方式相同,但只是将所有cookie处理复杂性隐藏在一个帮助器类中。它不包含内置的&#34;最大年龄&#34;处理,但这可以很容易地添加为一种解决方法,你可以手动&#34;编码&#34;年龄变成饼干价值。

顺便说一句。不知道你在做什么,但如果你碰巧使用TouchKit附加组件,它有一个帮助html5本地存储。它已经具有相当广泛的浏览器支持,并且在许多方面存储更好的方式,例如设置比饼干。