2017-01-05 61 views
7

我在服務器端使用Spring緩存(使用EHCache)來定義@Cacheable中的緩存鍵。問題在於不同的客戶端發送相同的字符串,這些字符串被用作具有不同拼寫的鍵,因爲它們會發送區分大小寫。結果是我的緩存包含的對象比他們要的要多。如何在Spring緩存中避免區分大小寫的鍵?

實施例: 比方說,我已經爲一定的方法中定義的以下緩存:

現在
@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和@CachePut(s),如果我將使用「toLowerCase」方法,我將永遠不要忘記它在任何地方。

+0

也許這是非常有用的,有自己的KeyGenerator http://stackoverflow.com/questions/27574786/generating-unique-cache-key-with-spring-keygenerator-not-working – gaston

+0

我想你可以委託到另一種實現實際緩存*的方法*之後,您可以對鍵進行所需的修改 –

回答

0

正如@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); 
    } 
} 

原始實現產生密鑰使用SimpleKey類時@Cacheable方法具有多於一個的參數。 這是用於生成不區分大小寫的密鑰的另一個實現。

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) + "]"; 
    } 
} 
相關問題