【问题标题】:EE8 JCache annotation CacheResult doesn't workEE8 JCache 注释 CacheResult 不起作用
【发布时间】:2019-09-06 13:55:39
【问题描述】:

我正在使用 EhCache 作为 JCache 实现 (JSR 107) 在 JBoss EAP 7.2 (EE8) 下开发一个 WEB 应用程序

我有这个代码:

@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

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) 

现在可以了,但是我想知道我可以保存所有这些代码和类以使其正常工作:/

【问题讨论】:

    标签: java ehcache jcache java-ee-8


    【解决方案1】:

    RI 默认将密钥包装到DefaultGeneratedCacheKey。您需要更改您的 EHCache 配置以允许密钥的 Object 类型。或者,您可以注册自己的密钥生成器并使用自己的密钥类型。当然,您也可以在 EHCache 配置中指定 org.jsr107.ri.annotations.DefaultGeneratedCacheKey,但是,您可以绑定到特定的实现。

    不幸的是,注释的 JSR107/JCache 标准要求缓存键实现接口GeneratedCacheKey。这意味着,如果您有一个简单的缓存键,如 int 或 string,则在存储到缓存中时,它们总是需要包装。

    旁注:接口GeneratedCacheKey 没有技术需求,因为它没有定义任何新方法。这是标准中的一个已知问题。不幸的是,在标准最终确定之前,没有对注释部分进行充分的审查。

    【讨论】:

    • 感谢您的回复,它证实了我的猜测。在这里,我找到了一些实现示例,github.com/tomitribe/jcache-cdi/blob/master/README.adoc,顺便说一句,我希望未来的规范会改进这个实际的规范
    • 你认为我可以保存任何锅炉代码吗?看看我上次的编辑
    • @FabrizioStellato:我也在考虑这个问题。它不仅是样板文件,而且对资源也不友好,因为您不需要缓存中的包装器/装饰器。您可以在缓存中包装/解包。我在这里为此构建了一些东西:github.com/cache2k/cache2k/blob/master/cache2k-jcache/src/main/… 也许分叉 cdi 实现并至少为包装的原始键制定一个伪标准是个好主意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    • 2013-09-20
    • 2020-10-09
    • 2012-09-19
    • 2015-09-14
    相关资源
    最近更新 更多