I have method without parameters and I want to cache return value. As cache key I want to use current authenticated user from security context
@Cacheable(value = "resultCache", key="#userPrincipal.id")
public result getResult() {}
Is it possible or my idea is wrong.
You have four options to achieve this:
Send the Authentication
object as a method parameter:
@Cacheable(value = "resultCache", key="#authentication.name")
public Result getResult(Authentication authentication) {}
Create a custom KeyGenerator
and use it in your @Cacheable
annotation
public class CustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
}
@Configuration
@EnableCaching
public class CacheConfiguration {
@Bean("customKeyGenerator")
public KeyGenerator customKeyGenerator() {
return new CustomKeyGenerator();
}
}
@Cacheable(value = "resultCache", keyGenerator="customKeyGenerator")
public Result getResult() {}
Create a bean that provides you the key and references it via SPeL in the key
property. I would recommend you going for this approach since it allows you to change the value later more easily.
@Component
public class CacheKeyProvider {
public String getUsernameKey() {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
}
@Cacheable(value = "resultCache", key="@cacheKeyProvider.getUsernameKey()")
public Result getResult() {}
Use the Type SpEL expression
@Cacheable(value = "resultCache", key="T(org.springframework.security.core.context.SecurityContextHolder.getContext()?.authentication?.name)")
public Result getResult() {}
Note that I used the name
property from the Principal
in the examples. But if you have a custom Principal
object you can cast it and return any property you want.