2

我正在尝试使用 Spring MVC 制作这个 2 人网络游戏应用程序。我有会话范围的 beanPlayer和应用程序范围的 bean GameList,它们创建和存储Game实例并将它们传递给Players. 玩家创建游戏并从中获取其 ID GameList,其他玩家将 ID 发送到GameList并获取Game实例。该Game实例将其玩家作为属性。问题是每个玩家只看到自己而不是另一个。

每个玩家看到的示例:

  1. 第一个玩家(Alice)创建一个游戏:Creator: Alice, Joiner: Empty
  2. 第二个玩家(鲍勃)加入游戏:Creator: Bob, Joiner: Bob
  3. 第一个玩家刷新她的浏览器Creator: Alice, Joiner: Alice

我想让他们看到的是Creator: Alice, Joiner: Bob。实现这一点的简单方法是保存有关玩家的信息而不是对玩家的引用,但是游戏对象需要调用其玩家对象的方法,因此这不是解决方案。

我认为这是因为aop:scoped-proxy会话范围的 Player bean。如果我理解这一点,那么 Game 对象引用了代理,它指的是当前会话的 Player 对象。Game 实例可以以某种方式保存/访问其他 Player 对象吗?

dispatcher-servlet.xml中的 bean :

<bean id="userDao" class="authorization.UserDaoFakeImpl"  />
<bean id="gameList" class="model.GameList" />
<bean name="/init/*" class="controller.InitController" >
     <property name="gameList" ref="gameList" />
     <property name="game" ref="game" />
     <property name="player" ref="player" />
</bean>
<bean id="game" class="model.GameContainer" scope="session">
      <aop:scoped-proxy/>
</bean>
<bean id="player" class="beans.Player" scope="session">
      <aop:scoped-proxy/>
</bean>

controller.InitController中的方法

private GameList gameList;
private GameContainer game;
private Player player;
public ModelAndView create(HttpServletRequest request,
        HttpServletResponse response) throws Exception {        
    game.setGame(gameList.create(player));        
    return new ModelAndView("redirect:game");
}
public ModelAndView join(HttpServletRequest request,
        HttpServletResponse response, GameId gameId) throws Exception {
    game.setGame(gameList.join(player, gameId.getId()));       
    return new ModelAndView("redirect:game");
}

model.gameList中调用的方法

public Game create(Player creator) {        
    Integer code = generateCode();        
    Game game = new Game(creator, code);
    games.put(code, game);
    return game;
}
public Game join(Player joiner, Integer code) {
    Game game = games.get(code);
    if (game!=null) {
        game.setJoiner(joiner);           
    }
    return game;
}
4

3 回答 3

2

您不能从应用程序范围访问不同的会话范围 bean。

但是,您可以做相反的事情 - 在应用程序范围的 bean 中注册每个播放器,(通过调用addPlayer(..)

于 2010-05-24T13:57:45.693 回答
1

我相信您对代理的看法是正确的,因为您只能看到自己。对代理的任何引用将仅适用于会话中的对象。

您是否需要将游戏和玩家设置为会话范围?您尝试跨会话使用它们的事实表明它们不是会话范围的数据。您可以从工厂创建它们并将它们的引用存储在会话范围的 bean 中。

或者,如果您确实希望播放器具有会话范围,您可以在会话 bean 中包装对原型的引用。然后,您可以将原型引用用于跨会话数据,并将会话 bean 用于任何特定于会话的本地数据。

有几种方法可以解决这个问题,但本质上,您需要将跨会话数据从会话范围的 bean 中移出,并移到可以共享的应用程序范围的 bean 中。

于 2010-05-24T13:54:57.980 回答
1

是的,最简单的方法是使用以下注释创建代理:

@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)

从 Spring 3.1 开始可用。在过去,您必须在 XML 配置中使用 aop:scoped-proxy 标记

于 2014-05-22T08:41:16.840 回答