2012-03-26 17 views
1

Ich habe mit den Spring 3.1 Cache-Abstraktionsfunktionen experimentiert und habe sie zum Laufen gebracht, aber wir haben einige benutzerspezifische Daten, die ich mit Session-Scoped-Beans zwischenspeichern möchte.Spring 3.1 Session Scoped Beans für Cache

Mein Cache-config.xml (importierte in 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> 

Ich habe RequestContextListener und Context in web.xml. Aber jedes Mal wenn ich versuche, mein Cache-Objekt autowire ich die folgende Meldung:

Fehler Bean mit dem Namen ‚scopedTarget.accountSettingsCache‘ zu erstellen: Scope ‚Sitzung‘ ist nicht aktiv für den aktuellen Thread; Betrachten Sie Definieren eines Bereichs Proxy für diese Bean, wenn Sie beabsichtigen, darauf Bezug zu nehmen von einem Singleton; verschachtelte Ausnahme ist java.lang.IllegalStateException: Keine fadengebundene Anfrage gefunden: Beziehen Sie sich auf Anforderungsattribute außerhalb einer tatsächlichen Web-Anfrage, oder die Verarbeitung einer Anfrage außerhalb der ursprünglich empfangenden Thread? Wenn Sie tatsächlich innerhalb einer Webanforderung arbeiten und diese Nachricht weiterhin erhalten, ist Ihr Code wahrscheinlich außerhalb von DispatcherServlet/DispatcherPortlet ausgeführt: In diesem Fall RequestContextListener oder RequestContextFilter verwenden, um die aktuelle Anforderung offen legen.

Ich habe spring-aop-3.1.1.RELEASE.jar in meinem Klassenpfad. Ich habe versucht, einen Wrapper für ConcurrentMapCache zu schreiben, der einen Standardkonstruktor ohne Parameter hat, so dass ich proxy-target-class auf true setzen kann. Ich habe versucht, sie außerhalb des CacheManagers zu deklarieren und sie später zur Liste der Caches hinzuzufügen.

Aber jedes Mal, wenn ich versuche, es als eine Eigenschaft oder Autowire es in einer Klasse (@Service oder @Controller) zu setzen, gibt es mir den gleichen Fehler. Es ist, als ob der aop: scoped-proxy völlig ignoriert wird.

Ich habe auch versucht ehCache und es hat funktioniert, aber es scheint nicht Session Coping Caching zu unterstützen. Ich könnte auch versuchen, einen benutzerdefinierten keyGenerator zu schreiben und die sessionId als Teil des Schlüssels im Cache verwenden, aber dann müsste ich den Lebenszyklus verwalten, es könnte eine Ablaufzeit haben, aber ich möchte eine bessere Kontrolle über die Daten im Cache . Irgendwelche Ideen?

Danke.

+1

Ich glaube nicht, Sie Session-scoped Bohnen in Ihrem Cache verwendet werden soll. Für sessiongebundene Beans sollte nur eine normale Session-Scoped-Bean ohne den Cache ausreichen. Wenn Sie einen Cache verwenden möchten, wäre die Verwendung von normalen booleschen Beans in Ordnung, und Sie würden die Session-ID irgendwo im Cache-Schlüssel verwenden. –

+0

Aber warum kann ich nicht eine Session-Bean in eine @ Service-Klasse senden? –

+0

Das ist möglich, aber anders als die obige Frage. Ist das etwas anderes? Wenn Sie pro Sitzung einen 'SimpleCacheManager' erstellen möchten, müssen Sie diesen Bean-Session-Bereich angeben. Ansonsten haben Sie einfach eine Session-Bean "shoppingCart" oder was immer Sie brauchen, und verbinden Sie diese mit Ihrem Controller. Aber ich kann nicht verstehen, warum Sie eine Cache-Ebene nur für session-beschränkte Beans benötigen. –

Antwort

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> 
Verwandte Themen