문제

I need your expertise :)

I'm working on a application where method calls on a service need to be authenticated. That means I want each method call to be cached with a key containing the username (to avoid for an unauthorized user to retrieve information cached by an authorized one).

With a personnalized KeyGenerator, all works fine.

Example of my key : username:USERNAME.appVersion:VERSION.METHOD.PARAM1.etc

But at some location, I got methods that retrieve a national content : this one will be the same for each user. And I want to avoid a cache key for each user asking for this content.

Example : appVersion:VERSION.METHOD.PARAM1.etc

So when I'm positioning my @Cacheable annotations, is there any way to set a new parameter in it ? The Key Generator will be able to catch it and know if he had to prefix the cache key name with user information or not.

Thanks for your help :)

Take care

도움이 되었습니까?

해결책

I don't really understand what you're saying by "set a new parameter in it". That parameter should come from somewhere right?

KeyGenerator gives you access to the Method, the actual instance and the method arguments. You may want to have a specific KeyGenerator for this particular cache operation which is something that will be available as from Spring 4.1 but in the mean time you can implement a composite that invokes the right KeyGenerator instance based on the method or, for instance, an annotation you have created to flag it.

다른 팁

Thank you snicoll, that was crystal clear and you really helped me a lot :)

Waiting for Spring 4.1, my team and I decided to use a custom @SharedCache annotation.

Here is some code samples to help if someone is in the same situation.

  • Given an existing custom GenericKeyGenerator (he's building a custom cache key for each cached method invocation)

  • We have a new custom AuthenticatedGenericKeyGenerator : he's inherited from GenericKeyGenerator and simply prefixing the cache key with user information

The application is now using AuthenticatedGenericKeyGenerator by default :

<cache:annotation-driven key-generator="keyGenerator"/>

<bean id="keyGenerator" class="your.package.AuthenticatedGenericKeyGenerator" />

AuthenticatedGenericKeyGenerator.java in details :

public class AuthenticatedGenericKeyGenerator extends GenericKeyGenerator {

    public AuthenticatedGenericKeyGenerator() {

        super(...);
    }

    @Override
    public Object generate(final Object target, final Method method, final Object... params) {

        String cacheKey = super.generate(target, method, params).toString();

        if(!method.isAnnotationPresent(SharedCache.class)) {

            cacheKey =  "user:" + some user information + "." + cacheKey;
        }

        return cacheKey;
    }

}

Our custom @SharedCache annotation :

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface SharedCache {

}

Now we just have to annotate @Cacheable methods with an extra @SharedCache if we want the cache key to be shared and not be unique (with an user id for example).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top