春天redis错误的结果

时间:2015-04-16 10:33:15

标签: spring redis

我正在使用Spring Redis和@Cacheable注释两种方法。当我调用一个方法时,我得到了另一个方法的缓存结果。

当我使用@Cachebale注释为每个方法配置不同的缓存时,如何从错误的缓存中获取结果?

设置:Spring版本4.1.6。 Redis数据1.5和Redis客户端2.7.0。

示例代码:

@Cacheable("test1")
    public List<String> findSgsns() {
}

@Cacheable("test2")
    public List<String> findSgsns2() {
}

2 个答案:

答案 0 :(得分:0)

通过将以下设置添加到弹簧配置(设置usePrefix)来解决问题:

<bean
    id="cacheManager"
    class="org.springframework.data.redis.cache.RedisCacheManager"
    c:template-ref="redisTemplate">
    <property name="usePrefix" value="true" />
</bean>

答案 1 :(得分:0)

默认情况下,如果您未在SimpleKeyGenerator注释中指定密钥,则Spring会使用@Cacheable生成密钥。

public class SimpleKeyGenerator implements KeyGenerator {

@Override
public Object generate(Object target, Method method, Object... params) 
{
    return generateKey(params);
}

/**
 * Generate a key based on the specified parameters.
 */
public static Object generateKey(Object... params) {
    if (params.length == 0) {
        return SimpleKey.EMPTY;
    }
    if (params.length == 1) {
        Object param = params[0];
        if (param != null && !param.getClass().isArray()) {
            return param;
        }
    }
    return new SimpleKey(params);
}
}

由于两个方法(findSgsns() and findSgsns2())中都没有方法参数,因此它基本上会为两个方法生成相同的缓存键。

您已经找到了一个基本上利用usePrefix bean中的redisTemplate属性的解决方案,这实际上为您增加了价值(即&#34; test1&#34;和&#34 ; test2&#34;)您在@Cacheable注释中指定它在Redis中形成缓存键时。为了完整起见,我想再提两个替代方案:

  1. 为每种方法指定自己的密钥(注意:您可以使用Spring EL指定密钥):

    @Cacheable(value = "test1", key = "key1")
    public List<String> findSgsns() {
    }
    
    @Cacheable(value = "test2", key = "key2")
    public List<String> findSgsns2() {
    }
    
  2. 构建自定义密钥生成器,下面是示例密钥生成器,它将方法名称转换为redis缓存密钥生成(注意:自定义密钥生成器将通过扩展CachingConfigurerSupport类自动生效):

    @Configuration
    public class RedisConfig extends CachingConfigurerSupport {
    
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
    
    }