问题:
启用了Spring且将范围设置为Request的缓存需要由不在请求范围内的singleton bean访问。
解:
Spring使您能够创建缓存,该缓存为请求范围保留数据。 例如
import org.springframework.cache.concurrent.ConcurrentMapCache; import org.springframework.cache.interceptor.SimpleCacheResolver; import org.springframework.cache.support.SimpleCacheManager; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; import java.util.ArrayList; import java.util.Collection; @Component @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) public class RequestScopeCache extends SimpleCacheResolver { public RequestScopeCache() { SimpleCacheManager cacheManager = new SimpleCacheManager(); Collection caches = new ArrayList((Collection) new ConcurrentMapCache( "myCache" , true )); cacheManager.setCaches(caches); cacheManager.initializeCaches(); setCacheManager(cacheManager); } }
您可以在要缓存的任何方法周围使用此缓存
@Cacheable(value = "myCache" , cacheResolver = "requestScopeCache" ) public String getName(String id) { //logic to get name from id }
现在,如果您从具有请求上下文的任何控制器中调用此方法,那就很好了,即,该方法是从服务Web请求的Spring bean的任何其他方法中调用的。
但是,如果您需要从线程池或fork连接池中调用它,事情就会变得棘手。 假设您收到一个请求,并且需要生成多个线程以同时运行以收集数据以将请求存储到服务器。
这些线程耗尽了Web请求线程的上下文,因此在Web请求线程上设置的任何“线程本地”值将对这些线程不可用。
因此,如果最终从这些池线程中调用上述方法(注释为使用缓存),则会从spring中获取异常,例如:
Scope 'session' is not active for the current thread ; IllegalStateException: No ; IllegalStateException: No thread -bound request found
但是有一种简单的方法可以修复它:
- 从Web请求线程获取请求属性
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
2.将此属性传递给来自pool或fork / join的自定义线程。 基本上可以通过在构造函数中使用此属性创建可运行对象来完成
3.在调用标记为使用请求范围缓存的方法之前,设置请求属性
RequestContextHolder.setRequestAttributes(attributes);
这将在当前线程的本地线程中设置属性,该属性可用于调用上述方法。
测试用例中的综合要求
现在,如果您正在从junit测试方法,则可能根本没有请求对象。
因此,您可以创建一个并按上述方法使用它来填充要测试的属性
RequestContextHolder.setRequestAttributes( new ServletRequestAttributes( new DummyRequest()));
翻译自: https://www.javacodegeeks.com/2020/05/access-spring-request-scope-cache-in-singelton-bean-called-from-fork-join-thread-pool.html