我有一个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);
的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做一些事情。为什么呢?
我找到了一种方法,如何获得所需的sessionscope -like功能。不要使用@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上测试了这种方法,它可以工作(在浏览器会话中保存信息)。