Spring MVC:来自两个不同会话的会话bean

时间:2011-08-22 12:34:25

标签: java spring session spring-mvc

我面临的问题的(简化)版本如下,在Spring MVC应用程序中:

两名球员可以参加比赛。该游戏包括从相同数据(例如某个国际象棋位置)开始,单独玩游戏(但同时玩!)并在之后比较结果。为了解决这个问题,我有:

  • 处理游戏的对象(例如,检查玩家是否准备好,生成开始数据,检查游戏是否完成,......)。我们称之为“GameHandler”,以便于参考。
  • 对于每个玩家,一个处理游戏动作的对象(例如,在棋盘上移动棋子)。这是一个会话范围的bean,因为它包含特定于播放器的状态信息。称之为'PlayerHandler':

    < bean id =“playerHandler”class =“snip.PlayerHandler”scope =“session”>     < aop:scoped-proxy /> < /豆腐>

问题是GameHandler需要重新同时使用两个PlayerHandler。但是,由于这是一个代理会话范围的bean,这些引用指向同一个bean,具体取决于我用来访问它的会话。例如。两个球员,“汤姆”和“杰里”:

会话Tom:playerHandler.getGameHandler().getPlayer1().getName()playerHandler.getGameHandler().getPlayer2().getName()都是Tom 会议杰瑞:都是杰瑞。

现在,据我了解,这是预期的行为。我的问题是“为什么会这样”,这是“我该如何解决这个问题”。我发现自己的解决方案是在GameHandler中设置引用时引用实际的bean而不是代理:

public void setPlayerOne(PlayerHandler playerHandler) {
try {
        while (playerHandler instanceof Advised)
            playerHandler = (PlayerHandler ) ((Advised) playerHandler ).getTargetSource().getTarget();
    } catch (Exception e) {
        e.printStackTrace();
}
...

但是,我不确定这是最好的解决方案。所以我正在寻找一些答案:我的设计是错误的 - 如果是这样,你会如何设计?我错过了一个简单的解决方案吗?这是春季限制吗?

2 个答案:

答案 0 :(得分:1)

回到你的基本设计,你必须重新考虑你的“PlayerHandler”是否真的是会话范围的,从概念上来说。由于您需要在给定会话范围之外访问它(处理特定会话请求的线程),因此它看起来不是。

重构这种方法的一种方法是将“PlayerHandler”移出到应用程序范围。创建一个全局单例bean,可能称之为“PlayerHandlerHolder”,例如,使用一个映射来保存键入会话ID的PlayerHandler实例。为了防止无限填充此映射,您可以实现一个会话侦听器,在会话销毁时从映射中删除PlayerHandler实例。

答案 1 :(得分:0)

解决问题的一种方法是create a custom scope,称之为“游戏”。现在像这样定义你的bean:

<bean id="playerHandler" class="snip.PlayerHandler" scope="game">
<aop:scoped-proxy /></bean>