我可以从应用程序范围的bean中访问Spring会话范围的bean吗?怎么样?

时间:2010-05-24 13:31:20

标签: java spring jsp session-scope

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

每个玩家看到的内容示例:

  1. 第一个玩家(Alice)创建一个游戏:Creator: Alice, Joiner: Empty
  2. 第二位玩家(Bob)加入游戏:Creator: Bob, Joiner: Bob
  3. 第一位玩家刷新浏览器Creator: Alice, Joiner: Alice
  4. 我希望他们看到的是Creator: Alice, Joiner: Bob。实现这一目标的简单方法是保存有关玩家的信息而不是对玩家的引用,但游戏对象需要在其玩家对象上调用方法,因此这不是解决方案。

    我认为这是因为会话范围的Player bean的aop:scoped-proxy。如果我理解了这一点,Game对象就引用了proxy,它引用了当前session的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 个答案:

答案 0 :(得分:2)

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

但是,您可以采取相反的方式 - 在应用程序范围的bean中注册每个玩家,(通过调用addPlayer(..)

答案 1 :(得分:1)

我相信你的代理权是正确的,因为你只看到自己。对代理的任何引用都只适用于会话中的对象。

你需要拥有游戏吗?    玩家作为会话范围?事实    你正试图使用​​它们    跨会话表明    他们不是会话范围的数据。您可以从工厂创建它们并将它们的引用存储在会话范围的bean中。

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

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

答案 2 :(得分:0)

您无法在HTTP会话中拥有游戏数据,因为它只属于一个用户。

您需要在创建者和加入者的会话中存储对游戏的引用。

答案 3 :(得分:0)

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

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

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