我试图实施棘手的事情并需要一些新的想法。 问题是:
想象一下Component1,它正在为集合中的每个用户执行一些操作。 就像
for (User user : users) {
doSomeStuff(user);
}
这些操作有一些共同的部分,这些部分非常耗时,因此目标只是执行一次(它们包括一些数据库查询等)。
想象一下这个耗时的方法之一:
public Object buildSomething(Object context) {
// some business logic here
}
我们的想法是存储结果并将其分享给其他用户,例如
public Object buildSomething(Object context) {
if (sharedResource.contains('something') {
return sharedResource.get('something');
} else {
// some business logic here
sharedResource.put('something', something)
return something;
}
}
谜语是 - 如何实现这个共享资源?
必须说,这是一个巨大的多层Web应用程序,我们不能只改变doSomeStuff方法并在那里添加一个上下文持有者参数,或类似的东西。
我分析了以下变种:
会话范围bean(生成buildSomething的东西)
问题:用户可以从应用程序注销,使用其他用户名/密码登录,他仍然会有相同的Http会话,这意味着他将获得具有先前请求状态的相同bean
upd:使用会话范围的另一个问题是基于弹簧的线程池调度程序,它可以在没有任何http会话的情况下调用Component1。
ThreadLocal变量
问题:我们处于Web应用程序上下文中,当线程返回池时,它可以用于其他用户请求
我试图找到第二个问题的解决方法,我的问题是:
是否可以分析堆栈跟踪元素并确保buildSomething方法的两次调用是由单个用户请求引起的?
关注Tx
答案 0 :(得分:0)
我认为会话范围的bean是更好的解决方案。您可以管理会话被销毁或创建的时间。当用户注销时,您需要调用“HttpSession.invalidate()”。
有一篇关于会话生命周期管理的好文章。 http://docstore.mik.ua/orelly/java-ent/servlet/ch07_05.htm
您还可以使用HttpSession工具在会话中存储信息(例如用户名)。
萨吕!
答案 1 :(得分:0)
我决定将此解决方案发布到此问题,现在可以在生产服务器上运行。
它基于ThreadLocal变量,该变量将信息保存在请求范围内。
最初的问题在于,不同的客户端可以重用单个线程,因为线程存储在池中。这个事实不允许按原样使用会话bean和线程本地。
所以我必须检查所有入口点,用户请求来到我的应用程序层。当我检测到请求时,我清除了请求的线程本地上下文。它起作用了,因为请求来到应用层的方式很少:它可能是来自另一层的服务请求,可以通过AOP和调度程序作业拦截,可以被自定义ThreadPoolExecutor拦截。