2017-01-05 25 views
7

Tôi đang sử dụng Spring caching (với EHCache) ở phía máy chủ xác định (các) khóa bộ nhớ cache trong @Cacheable. Vấn đề là các khách hàng khác nhau gửi cùng một chuỗi được sử dụng như các phím với cách viết khác nhau khi họ gửi trường hợp nhạy cảm. Kết quả là bộ đệm của tôi chứa nhiều đối tượng hơn là chúng phải có.Làm cách nào để tránh các phím nhạy cảm trong bộ nhớ đệm của Spring?

Ví dụ: Hãy nói rằng tôi có các bộ nhớ đệm sau định nghĩa cho một phương pháp nhất định:

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

Bây giờ khách hàng A gửi "abc" (tất cả chữ thường) để điều khiển. Bộ điều khiển gọi getFoo và "abc" được sử dụng làm chìa khóa để đặt một đối tượng vào bộ nhớ cache. Máy khách B gửi "abC" (chữ hoa C) và thay vì trả về đối tượng được lưu trong bộ đệm cho khóa "abc", đối tượng bộ nhớ cache mới cho khóa "abC" được tạo.

Làm cách nào để tránh các khóa có phân biệt chữ hoa chữ thường?

Tôi biết tôi có thể định nghĩa phím bộ nhớ cache để được chữ thường như thế này:

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

Đây là khóa học làm việc. Nhưng tôi đang tìm một giải pháp tổng quát hơn. Tôi có nhiều cache và nhiều khóa cache và làm một số @CacheEvict (s) và @CachePut (s) và nếu tôi sử dụng phương pháp "toLowerCase", tôi luôn phải đảm bảo không quên nó ở bất cứ đâu.

+0

Có lẽ đây là hữu ích, có của riêng KeyGenerator http://stackoverflow.com/questions/27574786/generating-unique-cache-key-with-spring-keygenerator-not-working – gaston

+0

Tôi nghĩ rằng bạn có thể ủy sang phương pháp khác thực hiện bộ nhớ đệm thực tế * sau * bạn thực hiện các sửa đổi mong muốn cho các phím –

Trả lời

0

Như @gaston đã đề cập, giải pháp thay thế mặc định KeyGenerator. Triển khai org.springframework.cache.annotation.CachingConfigurer hoặc mở rộng org.springframework.cache.annotation.CachingConfigurerSupport trong số Configuration của bạn.

@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; 
    } 
} 

Đây là triển khai được sửa đổi từ 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); 
    } 
} 

Việc thực hiện ban đầu sản xuất chủ chốt sử dụng SimpleKey lớp khi @Cacheable phương pháp có nhiều hơn một cuộc tranh cãi. Đây là một triển khai khác để tạo khóa không phân biệt chữ hoa chữ thường.

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) + "]"; 
    } 
} 
Các vấn đề liên quan