【问题标题】:How to avoid case sensitive keys in Spring cache?如何避免 Spring 缓存中区分大小写的键?
【发布时间】:2017-05-19 23:43:18
【问题描述】:

我在服务器端使用 Spring 缓存(使用 EHCache)在 @Cacheable 中定义缓存键。问题是不同的客户端发送相同的字符串,这些字符串用作具有不同拼写的键,因为它们区分大小写。结果是我的缓存包含的对象比它们必须的要多。

示例: 假设我为某个方法定义了以下缓存:

@Cacheable(value = "myCache", key="{#myString}")
public SomeBusinessObject getFoo(String myString, int foo){
...
}

现在客户端 A 向控制器发送“abc”(全小写)。控制器调用 getFoo 并且“abc”用作将对象放入缓存的键。 客户端 B 发送“abC”(大写 C),而不是返回键“abc”的缓存对象,而是创建键“abC”的新缓存对象。

如何避免按键区分大小写?

我知道我可以像这样将缓存键定义为小写:

@Cacheable(value = "myCache", key="{#myString.toLowerCase()}")
public SomeBusinessObject getFoo(String myString, int foo){
...
}

这当然有效。但我正在寻找更通用的解决方案。我有许多缓存和许多缓存键,并做了一些@CacheEvict(s) 和@CachePut(s),如果我要使用“toLowerCase”方法,我总是必须确保不要在任何地方忘记它。

【问题讨论】:

标签: java spring caching key case-insensitive


【解决方案1】:

正如@gaston 提到的,解决方案是替换默认的KeyGenerator。在您的Configuration 中实现org.springframework.cache.annotation.CachingConfigurer 或扩展org.springframework.cache.annotation.CachingConfigurerSupport

@Configuration
@EnableCaching
public class AppConfig extends CachingConfigurerSupport {
    @Override
    public KeyGenerator keyGenerator() {
        return new MyKeyGenerator();
    }

    @Bean
    @Override
    public CacheManager cacheManager() {
        //replaced with prefered CacheManager...
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("default")));
        return cacheManager;
    }
}

这是从org.springframework.cache.interceptor.SimpleKeyGenerator 修改的实现。

import java.lang.reflect.Method;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKey;

public class MyKeyGenerator implements KeyGenerator {

    @Override
    public Object generate(Object target, Method method, Object... params) {
        if (params.length == 0) {
            return SimpleKey.EMPTY;
        }
        if (params.length == 1) {
            Object param = params[0];
            if (param != null) {
                if (param.getClass().isArray()) {
                    return new MySimpleKey((Object[])param);
                } else {
                    if (param instanceof String) {
                        return ((String)param).toLowerCase();
                    }
                    return param;
                }
            }
        }
        return new MySimpleKey(params); 
    }
}

@Cacheable 方法有多个参数时,原始实现使用SimpleKey 类生成密钥。 这是生成不区分大小写键的另一种实现。

import java.io.Serializable;
import java.util.Arrays;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils; 
@SuppressWarnings("serial")
public class MySimpleKey implements Serializable {
    private final Object[] params;
    private final int hashCode;

    /**
     * Create a new {@link SimpleKey} instance.
     * @param elements the elements of the key
     */
    public MySimpleKey(Object... elements) {
        Assert.notNull(elements, "Elements must not be null");
        Object[] lceles = new Object[elements.length];
        this.params = lceles;
        System.arraycopy(elements, 0, this.params, 0, elements.length);
        for (int i = 0; i < elements.length; i++) {
            Object o = elements[i];
            if (o instanceof String) {
                lceles[i] = ((String)o).toLowerCase();
            } else {
                lceles[i] = o;
            }
        }
        this.hashCode = Arrays.deepHashCode(lceles);
    }

    @Override
    public boolean equals(Object obj) {
        return (this == obj || (obj instanceof MySimpleKey
                && Arrays.deepEquals(this.params, ((MySimpleKey) obj).params)));
    }

    @Override
    public final int hashCode() {
        return this.hashCode;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";
    }
} 

【讨论】:

    猜你喜欢
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    相关资源
    最近更新 更多