【发布时间】:2014-09-07 10:24:42
【问题描述】:
我有一个 Grails Web 应用程序,我需要在其中为每个用户会话保留一些数据。我不想使用 HTTP 会话,而是创建一个会话范围的 bean。下面给出的是我的 Session Scoped bean 定义 -
class SessionContainer implements Serializable {
static scope = 'session' (if I am using resources.groovy)
Boolean abc
Boolean def
Boolean xyz
SomeOtherChildBean someBean
}
这就是我的控制器的样子:
class MyController {
def myService
def showMyProblem() {
myService.updateSession()
myService.printSessionData()
}
}
这就是我的 Service 类的样子:
class MyService {
SessionContainer sessionContainer
def updateSession() {
sessionContainer.abc = true
sessionContainer.def = true
sessionContainer.xyz = true
}
def printSessionData() {
def abc = sessionContainer.abc
def def = sessionContainer.def
def xyz = sessionContainer.xyz
println abc // This is always false (which is incorrect)
println def // This is true (which is correct)
println xyz // This is true (which is correct)
}
}
我使用 2 种方式注入会话 bean - 在 resources.groovy -
sessionContainerBean(SessionContainer) { bean ->
bean.scope = 'session'
}
sessionContainer(org.springframework.aop.scope.ScopedProxyFactoryBean) {
targetBeanName = 'sessionContainerBean'
proxyTargetClass = true
}
或在 resources.xml 中
<bean id="sessionContainer" name="sessionContainer" class="com.dataobjects.SessionContainer" scope="session">
<aop:scoped-proxy/>
</bean>
我尝试了两种不同的方法来注入会话作用域 bean 来解决我的问题,尽管上面提到的任何一种方法都会导致相同的会话作用域 bean。
正如您从我的代码中看到的那样,我正在打印会话范围 bean 中的布尔变量,并且 abc 值始终为 false(这是不正确的)。打印其他布尔变量时,它会呈现正确的值。
我对会话 bean 为何对少数变量有正确的状态,却没有更新某些变量的状态感到震惊。
我什至尝试通过使用 (static scope = 'true') 来使用 Session Scoped 服务,但出现以下错误 - 我最终创建了一个代理范围服务,如此处所述 Grails session-scoped service - not working ,但行为与 Session Scoped bean 相同。
Error creating bean with name 'myService': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread
【问题讨论】:
-
服务类默认为单例。 myService 中的
sessionContainer可能来自其他请求,因为在服务类中为该变量维护了一个状态。 -
这就是为什么 'sessionContainer' 作为 Session Scoped 变量注入的原因。在基于 Spring 的应用程序中通常遵循相同的方法,其中会话范围的变量被注入到基于 Spring 的单例服务类中。