EE8 JCache 注释 CacheResult 不起作用
EE8 JCache annotation CacheResult doesn't work
我正在 JBoss EAP 7.2 (EE8) 下开发一个 WEB 应用程序,使用 EhCache 作为 JCache 实现 (JSR 107)
我有这个代码:
@Inject
CacheManager cacheManager;
@CacheResult(cacheName = "roles")
public List<RoleDTO> get(@CacheKey String id) {
return service.getRoles(id);
}
public List<RoleDTO> getRoles(final String userId) {
final List<RoleDTO> output = get(userId);
return output;
}
根据我读到的article,我希望我第二次访问 get(userId) 方法时应该使用缓存并忽略进入该方法,但事实并非如此。
我也查询了注入的cacheManager,"roles"缓存总是空的。
我哪里错了?
编辑
我猜 EhCache 3.x 在标准的 EE 环境中不支持 jcache 注释,在网络上我只能看到其他 CDI 实现,如 ri o guice。
但是,通过包括这些实现之一,例如:
<dependency>
<groupId>org.jsr107.ri</groupId>
<artifactId>cache-annotations-ri-cdi</artifactId>
</dependency>
似乎新的缓存条目被放入了一个新的缓存管理器(见下面的代码)
Caching.getCachingProvider().getCacheManager
而不是我已经拥有的注入和配置的 CacheManager
编辑编辑
@CacheResult(cacheName = "roles", cacheResolverFactory = AppCacheResolverFactory.class, cacheKeyGenerator = CacheKeyGeneratorFactory.class)
public List<RoleDTO> getRoles(@CacheKey final String userId) {
这是我的 CacheResolverFactory class
public class AppCacheResolverFactory implements CacheResolverFactory {
@Inject
CacheManager cacheManager;
@Override
public CacheResolver getCacheResolver(CacheMethodDetails<? extends Annotation> cacheMethodDetails) {
return new DefaultCacheResolver(cacheManager.getCache(cacheMethodDetails.getCacheName()));
}
@Override
public CacheResolver getExceptionCacheResolver(CacheMethodDetails<CacheResult> cacheMethodDetails) {
return null;
}
}
现在我明白了:
java.lang.ClassCastException: Invalid key type, expected : java.lang.String but was : org.jsr107.ri.annotations.DefaultGeneratedCacheKey
编辑编辑编辑
我创建了一个 CacheKeyGeneratorFactory 和一个包装字符串值的 StringCacheKey:
CacheKeyGeneratorFactory
public class CacheKeyGeneratorFactory implements CacheKeyGenerator {
@Override
public GeneratedCacheKey generateCacheKey(CacheKeyInvocationContext<? extends Annotation> cacheKeyInvocationContext) {
final CacheInvocationParameter[] allParameters = cacheKeyInvocationContext.getAllParameters();
for (CacheInvocationParameter parameter : allParameters) {
if (StringCacheKey.class.equals(parameter.getRawType())) {
return (StringCacheKey)parameter.getValue();
}
}
return null;
}
}
StringCacheKey
public class StringCacheKey implements GeneratedCacheKey {
private String value;
public StringCacheKey(String param) {
this.value = param;
}
@Override
public int hashCode() {
return this.value.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj != null && obj.getClass() == this.getClass() && this.value.equals(((StringCacheKey)obj).getValue());
}
public String getValue() {
return value;
}
}
然后我更改了 ehcache.xml 配置:
<cache alias="roles">
<key-type>mypackage.StringCacheKey</key-type>
<value-type>java.util.List</value-type>
还有@CacheResult 的方法
public List<RoleDTO> get(@CacheKey String id)
现在可以了,但是我想知道我是否可以保存所有这些代码和 class 以使其工作:/
注册机默认将keys包装成DefaultGeneratedCacheKey
。您需要更改您的 EHCache 配置以允许密钥的 Object
类型。或者,您可以注册自己的密钥生成器并使用您自己的密钥类型。你当然也可以在你的 EHCache 配置中指定 org.jsr107.ri.annotations.DefaultGeneratedCacheKey
,然而,然后你绑定到一个特定的实现。
不幸的是,JSR107/JCache 注释标准要求缓存键实现接口 GeneratedCacheKey
。这意味着,如果你有一个简单的缓存键,如 int 或 string,当存储到缓存中时,它们总是需要被包装。
旁注:接口 GeneratedCacheKey
没有技术需求,因为它没有定义任何新方法。这是标准中的已知问题。不幸的是,在标准最终确定之前没有对注释部分进行充分的审查。
我正在 JBoss EAP 7.2 (EE8) 下开发一个 WEB 应用程序,使用 EhCache 作为 JCache 实现 (JSR 107)
我有这个代码:
@Inject
CacheManager cacheManager;
@CacheResult(cacheName = "roles")
public List<RoleDTO> get(@CacheKey String id) {
return service.getRoles(id);
}
public List<RoleDTO> getRoles(final String userId) {
final List<RoleDTO> output = get(userId);
return output;
}
根据我读到的article,我希望我第二次访问 get(userId) 方法时应该使用缓存并忽略进入该方法,但事实并非如此。 我也查询了注入的cacheManager,"roles"缓存总是空的。
我哪里错了?
编辑
我猜 EhCache 3.x 在标准的 EE 环境中不支持 jcache 注释,在网络上我只能看到其他 CDI 实现,如 ri o guice。 但是,通过包括这些实现之一,例如:
<dependency>
<groupId>org.jsr107.ri</groupId>
<artifactId>cache-annotations-ri-cdi</artifactId>
</dependency>
似乎新的缓存条目被放入了一个新的缓存管理器(见下面的代码)
Caching.getCachingProvider().getCacheManager
而不是我已经拥有的注入和配置的 CacheManager
编辑编辑
@CacheResult(cacheName = "roles", cacheResolverFactory = AppCacheResolverFactory.class, cacheKeyGenerator = CacheKeyGeneratorFactory.class)
public List<RoleDTO> getRoles(@CacheKey final String userId) {
这是我的 CacheResolverFactory class
public class AppCacheResolverFactory implements CacheResolverFactory {
@Inject
CacheManager cacheManager;
@Override
public CacheResolver getCacheResolver(CacheMethodDetails<? extends Annotation> cacheMethodDetails) {
return new DefaultCacheResolver(cacheManager.getCache(cacheMethodDetails.getCacheName()));
}
@Override
public CacheResolver getExceptionCacheResolver(CacheMethodDetails<CacheResult> cacheMethodDetails) {
return null;
}
}
现在我明白了:
java.lang.ClassCastException: Invalid key type, expected : java.lang.String but was : org.jsr107.ri.annotations.DefaultGeneratedCacheKey
编辑编辑编辑
我创建了一个 CacheKeyGeneratorFactory 和一个包装字符串值的 StringCacheKey:
CacheKeyGeneratorFactory
public class CacheKeyGeneratorFactory implements CacheKeyGenerator {
@Override
public GeneratedCacheKey generateCacheKey(CacheKeyInvocationContext<? extends Annotation> cacheKeyInvocationContext) {
final CacheInvocationParameter[] allParameters = cacheKeyInvocationContext.getAllParameters();
for (CacheInvocationParameter parameter : allParameters) {
if (StringCacheKey.class.equals(parameter.getRawType())) {
return (StringCacheKey)parameter.getValue();
}
}
return null;
}
}
StringCacheKey
public class StringCacheKey implements GeneratedCacheKey {
private String value;
public StringCacheKey(String param) {
this.value = param;
}
@Override
public int hashCode() {
return this.value.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj != null && obj.getClass() == this.getClass() && this.value.equals(((StringCacheKey)obj).getValue());
}
public String getValue() {
return value;
}
}
然后我更改了 ehcache.xml 配置:
<cache alias="roles">
<key-type>mypackage.StringCacheKey</key-type>
<value-type>java.util.List</value-type>
还有@CacheResult 的方法
public List<RoleDTO> get(@CacheKey String id)
现在可以了,但是我想知道我是否可以保存所有这些代码和 class 以使其工作:/
注册机默认将keys包装成DefaultGeneratedCacheKey
。您需要更改您的 EHCache 配置以允许密钥的 Object
类型。或者,您可以注册自己的密钥生成器并使用您自己的密钥类型。你当然也可以在你的 EHCache 配置中指定 org.jsr107.ri.annotations.DefaultGeneratedCacheKey
,然而,然后你绑定到一个特定的实现。
不幸的是,JSR107/JCache 注释标准要求缓存键实现接口 GeneratedCacheKey
。这意味着,如果你有一个简单的缓存键,如 int 或 string,当存储到缓存中时,它们总是需要被包装。
旁注:接口 GeneratedCacheKey
没有技术需求,因为它没有定义任何新方法。这是标准中的已知问题。不幸的是,在标准最终确定之前没有对注释部分进行充分的审查。