使用@Push 读取和写入 cookie
Read and write cookies with @Push
在我的 vaadin 应用程序中,我需要使用 @Push
,但由于我添加了它,所以我无法读取和写入 cookie,因为 VaadinService.getSurrentResponse()
returns null 因为 Push
。我使用这个 class 管理 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 constructor 并在 addCookie()
方法结束时重新启用它,但它禁用了我所有应用程序的推送,即使我在 addCookie
方法.
我在 vaadin 的 trac (http://dev.vaadin.com/ticket/11808) 上看到一张票说不会修复,有人建议从服务器创建一个常规 AJAX 查询来创建 cookie,但我真的不不知道怎么办。
我如何管理我的cookies?我需要创建和获取 cookie,所以 javascript 帮不了我,因为我无法在 vaadin 中获取 javascript 的 return,所以我无法获取 cookie .
如前所述 in the ticket,您可以使用 JavaScript
调用客户端代码并请求返回一个 cookie 值。例如
@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
)。重要部分见评论
The Viritin add-on 包含一个名为 BrowserCookie 的助手 class。它的工作方式几乎与 cfrick 建议的方式相同,但只是将所有 cookie 处理的复杂性隐藏到一个助手 class 中。它不包含内置 "max age" 处理,但可以轻松添加作为解决方法,您可以手动 "encode" 将年龄输入 cookie 值。
顺便说一句。不知道你在做什么,但如果你碰巧使用 TouchKit 插件,它有一个 html5 本地存储的帮助程序。它已经有相当广泛的浏览器支持,并且在许多方面是更好的存储方式,例如设置比 cookie。
这是我在使用@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:
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 时遇到问题,所以这是我的工作解决方案。
在我的 vaadin 应用程序中,我需要使用 @Push
,但由于我添加了它,所以我无法读取和写入 cookie,因为 VaadinService.getSurrentResponse()
returns null 因为 Push
。我使用这个 class 管理 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 constructor 并在 addCookie()
方法结束时重新启用它,但它禁用了我所有应用程序的推送,即使我在 addCookie
方法.
我在 vaadin 的 trac (http://dev.vaadin.com/ticket/11808) 上看到一张票说不会修复,有人建议从服务器创建一个常规 AJAX 查询来创建 cookie,但我真的不不知道怎么办。
我如何管理我的cookies?我需要创建和获取 cookie,所以 javascript 帮不了我,因为我无法在 vaadin 中获取 javascript 的 return,所以我无法获取 cookie .
如前所述 in the ticket,您可以使用 JavaScript
调用客户端代码并请求返回一个 cookie 值。例如
@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
)。重要部分见评论
The Viritin add-on 包含一个名为 BrowserCookie 的助手 class。它的工作方式几乎与 cfrick 建议的方式相同,但只是将所有 cookie 处理的复杂性隐藏到一个助手 class 中。它不包含内置 "max age" 处理,但可以轻松添加作为解决方法,您可以手动 "encode" 将年龄输入 cookie 值。
顺便说一句。不知道你在做什么,但如果你碰巧使用 TouchKit 插件,它有一个 html5 本地存储的帮助程序。它已经有相当广泛的浏览器支持,并且在许多方面是更好的存储方式,例如设置比 cookie。
这是我在使用@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:
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 时遇到问题,所以这是我的工作解决方案。