英文:
Spring Boot cache not caching method call based on dynamic controller parameter
问题
我正在尝试在Spring Boot中使用Caffeine缓存管理器。我已经像这样将一个服务类注入到控制器中:
@RestController
@RequestMapping("property")
public class PropertyController {
private final PropertyService propertyService;
@Autowired
public PropertyController(PropertyService propertyService) {
this.propertyService = propertyService;
}
@PostMapping("get")
public Property getPropertyByName(@RequestParam("name") String name) {
return propertyService.get(name);
}
}
而PropertyService
看起来像这样:
@CacheConfig(cacheNames = "property")
@Service
public class PropertyServiceImpl implements PropertyService {
private final PropertyRepository propertyRepository;
@Autowired
public PropertyServiceImpl(PropertyRepository propertyRepository) {
this.propertyRepository = propertyRepository;
}
@Override
public Property get(@NonNull String name, @Nullable String entity, @Nullable Long entityId) {
System.out.println("inside: " + name);
return propertyRepository.findByNameAndEntityAndEntityId(name, entity, entityId);
}
@Cacheable
@Override
public Property get(@NonNull String name) {
return get(name, null, null);
}
}
现在,当我调用RestController的get
端点并提供一个名称值时,每个请求都会在应该被缓存的方法内部执行。
但是,如果我调用控制器的get
端点,但将硬编码的字符串传递到服务类方法中,像这样:
@PostMapping("get")
public Property getPropertyByName(@RequestParam("name") String name) {
return propertyService.get("hardcoded");
}
然后,该方法只在第一次调用时被调用,而在后续调用中不会被调用。
这里发生了什么?为什么在动态提供值时不会缓存方法调用?
以下是一些配置:
@Configuration
public class CacheConfiguration {
@Bean
public CacheManager cacheManager() {
val caffeineCacheManager = new CaffeineCacheManager("property", "another");
caffeineCacheManager.setCaffeine(caffeineCacheBuilder());
return caffeineCacheManager;
}
public Caffeine<Object, Object> caffeineCacheBuilder() {
return Caffeine.newBuilder()
.initialCapacity(200)
.maximumSize(500)
.weakKeys()
.recordStats();
}
}
英文:
I am attempting to use Spring Boot Cache with a Caffeine cacheManager.
I have injected a service class into a controller like this:
@RestController
@RequestMapping("property")
public class PropertyController {
private final PropertyService propertyService;
@Autowired
public PropertyController(PropertyService propertyService) {
this.propertyService = propertyService;
}
@PostMapping("get")
public Property getPropertyByName(@RequestParam("name") String name) {
return propertyService.get(name);
}
}
and the PropertyService
looks like this:
@CacheConfig(cacheNames = "property")
@Service
public class PropertyServiceImpl implements PropertyService {
private final PropertyRepository propertyRepository;
@Autowired
public PropertyServiceImpl(PropertyRepository propertyRepository) {
this.propertyRepository = propertyRepository;
}
@Override
public Property get(@NonNull String name, @Nullable String entity, @Nullable Long entityId) {
System.out.println("inside: " + name);
return propertyRepository.findByNameAndEntityAndEntityId(name, entity, entityId);
}
@Cacheable
@Override
public Property get(@NonNull String name) {
return get(name, null, null);
}
}
Now, when I call the RestController get
endpoint and supply a value for the name, every request ends up doing inside the method that should be getting cached.
However, if I call the controller get
endpoint but pass a hardcoded String into the service class method, like this:
@PostMapping("get")
public Property getPropertyByName(@RequestParam("name") String name) {
return propertyService.get("hardcoded");
}
Then the method is only invoked the first time, but not on subsequent calls.
What's going on here? Why is it not caching the method call when I supply a value dynamically?
Here is some configuration:
@Configuration
public class CacheConfiguration {
@Bean
public CacheManager cacheManager() {
val caffeineCacheManager = new CaffeineCacheManager("property", "another");
caffeineCacheManager.setCaffeine(caffeineCacheBuilder());
return caffeineCacheManager;
}
public Caffeine<Object, Object> caffeineCacheBuilder() {
return Caffeine.newBuilder()
.initialCapacity(200)
.maximumSize(500)
.weakKeys()
.recordStats();
}
}
答案1
得分: 2
2个解决方案(它们对我有效):
-
移除
.weakKeys()
-
propertyService.get(name.intern())
- 不建议这样做,可能会有很大的成本
抱歉,我没有足够的知识来解释这个。可能与Caffeine的内部键表示有关。
英文:
2 solutions (they work for me):
-
remove
.weakKeys()
-
propertyService.get(name.intern())
- wouldn't really do that, possibly a big cost
Sorry, but I don't have enough knowledge to explain this. Probably something to do with internal key representation by Caffeine.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论