【问题标题】:Grails Session Scoped bean data state not updated correctlyGrails Session Scoped bean 数据状态未正确更新
【发布时间】: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 的单例服务类中。

标签: session grails


【解决方案1】:

如果MyService 是在grails-app/services/ 下定义的真正Grails 服务,那么您不需要在resources.groovyresources.xml 中定义bean。您可以将范围表示为静态属性:

// grails-app/services/demo/MyService.groovy
package demo

class MyService {
    static scope = 'session'

    // ...
}

这有帮助吗?

【讨论】:

  • 您可能需要管理一些相关 bean 的范围,具体取决于您应用中的其他一些因素。
  • 嗨,杰夫,非常感谢您的回复。我不希望 MyService 是基于会话的,而是在 MyService 类中注入一个 Bean (SessionContainer)。我反对将服务类声明为 Session 范围的想法,因为服务应该是无状态的和单例的。
  • 您需要解决从单例 bean 引用会话范围 bean 的问题。
  • 您已经提交了您希望有一个会话范围的 bean 保持状态。如果您仍要这样做,只需使用会话范围的服务。您之所以引入复杂性,是出于我从描述中看不到的原因。
  • 说“服务应该是无状态的和单例的”,然后说“我有一个 Grails Web 应用程序,我需要在其中为每个用户会话保留一些数据”似乎表明你在教条在没有真正意义的情况下想要无状态服务。它是一种“服务”这一事实并不是这里真正的一个因素。您希望会话范围的 bean 保持状态。如果您希望这样做并认为这是一个好主意,那么为什么将 bean 用作服务会有问题?
猜你喜欢
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 2012-04-09
  • 2016-09-09
  • 2021-12-14
相关资源
最近更新 更多