我有一个Java项目,我使用Jersey(1.17)和Guice(3.0)。 SessionScoped bean在本地开发中工作,但在GAE上部署时不起作用。问题是他们没有保持会话状态。
在web.xml中启用了会话:<sessions-enabled>true</sessions-enabled>
我的会话bean(SessionService)是:
@SessionScoped
public class SessionService implements Serializable {
@Inject transient Logger log;
private Locale locale = Locale.US;
public synchronized Locale getLocale() { return locale; }
public synchronized void setLocale(Locale locale) { this.locale = locale; }
}
并且它绑定到ServletModule bind(SessionService.class).in(ServletScopes.SESSION);
我使用它的控制器是:
@Path("/settings")
public class SettingsController {
@Inject SessionService sessionService;
@GET
@Path("/setLocale")
public Object setLocale(@QueryParam("languageTag") String languageTag) {
sessionService.setLocale(Locale.forLanguageTag(languageTag));
return "OK";
}
@GET
@Path("/getLocale")
public Object getLocale() { return sessionService.getLocale().getLanguage(); }
}
使用本地开发服务器,它可以正常工作。当部署在GAE(1.9.5)上时,它首次设置语言环境,然后它永远保持不变,即使我一次又一次调用setLocale。为什么不起作用?
奇怪的是,我找到了一种让它起作用的模糊方法,但我不知道它为什么会起作用。要让它运行,必须在设置区域设置之前触摸HttpSession。像request.getSession(true).setAttribute("whatever", "bar")
一样。好像需要召回服务器,SessionService想要使用Session做一些事情。那是为什么?
答案 0 :(得分:1)
我找到了一种如何获得所需的SessionScoped功能的方法。不要使用@SessionScoped
,因为它显然不适用于GAE,而是使用Provider<HttpSession>
。
所以你的代码就像
public class SessionService {
@Inject Provider<HttpSession> httpSessionProvider;
public void saveSecurityInfo(Object securityInfo) {
httpSessionProvider.get().setAttribute('sec_info', securityInfo);
}
public Object loadSecurityInfo() {
return httpSessionProvider.get().getAttribute('sec_info');
}
}
在控制器中,您可以将其插入@Inject SessionService sessionService;
我已经在GAE上测试了这种方法,它可以工作(在浏览器会话中保存信息)。