2012-03-26 4 views
1

Я экспериментировал с функциями абстракции Spring 3.1 и заставлял их работать, но у нас есть некоторые пользовательские данные, которые я хотел бы кэшировать с использованием бранд-сессий.Spring 3.1 Session Scoped Beans for 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> 

У меня есть RequestContextListener и ContextLoaderListener в web.xml. Но каждый раз, когда я пытаюсь autowire моего объекта кэша я получаю следующее сообщение:

Ошибка создания боба с именем «scopedTarget.accountSettingsCache»: Scope «сессия» не активна для текущего потока; рассмотрите , определяющий прокси-объект с ограниченным доступом для этого компонента, если вы намереваетесь обратиться к нему из одноэлементного; nested exception is java.lang.IllegalStateException: Не найдено ни одного запроса, связанного с потоком: ссылаетесь ли вы на атрибуты запроса за пределы фактического веб-запроса или обрабатываете запрос за пределами изначально получающего потока? Если вы фактически работаете в пределах веб-запроса и все еще получаете это сообщение, возможно, ваш код работает за пределами DispatcherServlet/DispatcherPortlet: В этом случае использует RequestContextListener или RequestContextFilter для выставления текущего запроса .

У меня есть spring-aop-3.1.1.RELEASE.jar в моем классе. Я попытался написать обертку для ConcurrentMapCache, у которой есть конструктор по умолчанию без параметров, поэтому я могу установить для прокси-целевого класса значение true. Я попытался объявить их за пределами cacheManager и добавить их в список кешей позже.

Но каждый раз, когда я пытаюсь установить его как свойство или autowire его в классе (@Service или @Controller), он дает мне ту же ошибку. Как будто aop: scoped-proxy полностью игнорируется.

Я также пробовал ehCache, и это сработало, но похоже, что оно не поддерживает кеширование с сеансом. Я мог бы также попытаться написать собственный keyGenerator и использовать sessionId как часть ключа в кеше, но тогда мне придется управлять его жизненным циклом, у него может быть время истечения срока, но я хочу более тонкий контроль над данными в кеше , Любые идеи?

Спасибо.

+1

Я не думаю, что вы должны использовать контекст сеанса бобы в кэше. Для работы с сессионным компонентом должно быть достаточно обычного компонента с ограниченным сеансом без кеша. Если вы хотите использовать кеш, то использование обычных боковых областей будет прекрасным, и вы будете использовать идентификатор сеанса где-нибудь в ключе кеша. –

+0

Но почему он не позволяет мне авторизовать сеансовый компонент в класс @Service? –

+0

это возможно, но другой вопрос выше. Это что-то еще? Если вы хотите «SimpleCacheManager» за сеанс, тогда создайте этот сеанс в боковом сеансе. В противном случае у вас есть фасоль с сессией, называемая 'shoppingCart', или что вам нужно, и подключите ее к контроллеру. Но я не понимаю, почему вам нужен слой кеширования только для бонусов, связанных с сеансом. –

ответ

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> 
Смежные вопросы