簡體   English   中英

如何避免Spring緩存中的區分大小寫的密鑰?

[英]How to avoid case sensitive keys in Spring cache?

我在服務器端使用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”方法,我總是要確保不要忘記它在任何地方。

正如@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修改的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) + "]";
    }
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM