2

我有一个使用 Jersey (1.17) 和 Guice (3.0) 的 Java 项目。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 中的 Session 范围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 做一些事情。这是为什么?

4

1 回答 1

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 上测试了这种方法并且它有效(在浏览器会话中保留信息)。

于 2016-03-24T14:50:22.213 回答