我试图在会话的整个生命周期中将我的会话范围的用户bean存储在单例范围的控制器中。因此,无论何时连接用户,我都希望将其存储在一个数组中,其余用户将保留其会话。
我知道通过代理bean将会话范围的bean注入@Controller,以便我已经定义了我的会话范围的用户bean,如下所示,
@Bean
@Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public IUser user ()
{
IUser user = new MyUser();
return user;
}
我已经使用@Autowire注释将该bean注入我的控制器类,如下所示,
@Autowired
private IUser sessionUser;
因此,无论何时用户连接,我都将该用户存储在ConcurrentHashMap中,该地图已定义并添加如下,
private ConcurrentHashMap<Integer,IUser> userMap = new ConcurrentHashMap<>(50,0.9f,2);
public void addUser(IUser user)
{
if(user == null) return;
IUser retUser = userMap.putIfAbsent(user.getDbid(),user);
//...
}
当第一个用户连接时,一切正常,我将其引用存储到map。让我们假设第一个用户参考是
us.com.soemthing.orm.model.MyUser@135debf
然后让我们假设第二个用户连接的参考是
us.com.soemthing.orm.model.MyUser@28zbdh
从引用中,我可以看到我的会话范围的bean工作正常,因为它们的引用不同。 但,执行进入 addUser 方法时会出现问题。 甚至在将第二个用户添加到地图之前,我检查了我的userMap,看到它存储的用户对象被替换为第二个用户MyUser @ 28zbdh。所以在结束,添加第二个用户后,我的用户地图如下所示,
Map --> "1"- us.com.soemthing.orm.model.MyUser@28zbdh
Map --> "2"- us.com.soemthing.orm.model.MyUser@28zbdh
因此,引用始终与最后一个一起更新。我知道它们是真实对象的代理对象,但我如何存储它们?
由于
[编辑]我想提供更多信息。
我从另一个单例bean调用addUser,userInDBMemory.addUser(sessionUser); userInDBMemory是另一个单例bean,我将会话用户实际添加到ConcurrentHashMap。我想将我当前的在线用户存储在地图上,因为我想在不进入数据库的情况下搜索和查询它们。因此,我希望将内存用户(在上下文中具有会话)保留在内存中,以便更轻松,更快速地访问。为了处理会话过期,每个在线用户向服务器发送心跳以显示他在线,我在服务器上每隔X分钟运行一个预定线程,如果发现任何用户没有从用户那里获得心跳然后它将其从地图中删除,因为这意味着用户离线。总结我的情况我有一个主控制器,我得到请求,然后链是这样的:@ Controller-&gt;单例应用程序bean-&gt;单例inMemoryDB bean(我定义我的地图和添加用户)我的SessionUser会话范围的bean是@Autowired在@Controller中我将它作为参数传递给其他单例bean。谢谢你的回复。
答案 0 :(得分:0)
我通过不直接存储会话范围的bean但是它们的对象副本来解决我的问题。
//IMyUser sessionUser; --let say sessionUser is session-scoped bean in a singleton bean
所以代替;
userInDBMemory.addUser(sessionUser);
我先复制了用户并添加了该对象。
IMyUser copyUser = new MyUser();
BeanUtils.copyProperties(sessionUser, copyUser);
userInDBMemory.addUser(copyUser);