Spring 3.1 Session Scoped Beans for Cache

时间:2012-03-26 11:15:15

标签: spring session caching

我一直在试验Spring 3.1缓存抽象功能并让它们工作但我们有一些用户特定的数据,我想用会话范围的bean缓存它们。

我的cache-config.xml(导入到applicationContext.xml中):

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd    
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

  <!-- Activates various annotations to be detected in bean classes: Spring's @Required and @Autowired, as well as JSR 250's @Resource. -->

  <context:annotation-config />
  <context:component-scan base-package="my.package.whatevs" />

  <!-- <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="false" mode="proxy" /> -->
  <cache:annotation-driven cache-manager="cacheManager" />

   <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
    <property name="caches">
      <set>
        <bean id="defaultCache" class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="defaultCache" />

        <bean id="accountSettingsCache" class="org.springframework.cache.concurrent.ConcurrentMapCache" scope="session">
          <aop:scoped-proxy proxy-target-class="false" />
          <constructor-arg>
            <value>accountSettingsCache</value>
          </constructor-arg>
        </bean>

      </set>
    </property>
  </bean>

</beans>

我在web.xml中有RequestContextListener和ContextLoaderListener。 但每次我尝试自动装配我的缓存对象时,我都会收到以下消息:

  

创建名为'scopedTarget.accountSettingsCache'的bean时出错:   范围'session'对于当前线程不活动;考虑   如果您打算引用它,则为该bean定义范围代理   来自单身人士;嵌套异常是java.lang.IllegalStateException:   找不到线程绑定请求:您指的是请求属性吗?   在实际的Web请求之外,或处理外部的请求   原来收到的帖子?如果你实际在里面经营   一个Web请求仍然收到此消息,您的代码可能是   在DispatcherServlet / DispatcherPortlet之外运行:在这种情况下,   使用RequestContextListener或RequestContextFilter来公开   当前的要求。

我的classpath中有spring-aop-3.1.1.RELEASE.jar。 我尝试为ConcurrentMapCache编写一个包装器,它有一个没有参数的默认构造函数,所以我可以将proxy-target-class设置为true。 我尝试在cacheManager之外声明它们,然后将它添加到缓存列表中。

但每当我尝试将其设置为属性或在类(@Service或@Controller)中自动装配它时,它会给出同样的错误。 就像aop:scoped-proxy完全被忽略一样。

我也尝试过ehCache并且它有效,但它似乎不支持会话范围的缓存。 我也可以尝试编写一个自定义keyGenerator并使用sessionId作为缓存中密钥的一部分,但是我必须管理它的生命周期,它可能有一个到期时间,但我希望更好地控制缓存中的数据。 有任何想法吗 ?

感谢。

1 个答案:

答案 0 :(得分:0)

                                                                      

<bean id="sessionLevelCacheManager" class="org.springframework.cache.support.SimpleCacheManager"
    scope="session">
    <property name="caches">
        <set>
            <bean id="sessionCache"
                class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
                p:name="sessionCache">
            </bean>
        </set>
    </property>
    <aop:scoped-proxy proxy-target-class="false" />
</bean>

<bean id="compositeCacheManager" class="org.springframework.cache.support.CompositeCacheManager">
    <property name="cacheManagers">
        <array>
            <ref bean="applicationLevelCacheManager" />
            <ref bean="sessionLevelCacheManager" />
        </array>
    </property>
    <property name="fallbackToNoOpCache" value="true" />
</bean>