Sping Boot 2.6.14版本
控制器
@PostMapping("/v1/books)
public GenericResponse<Book> getBooks(BookRequest request) {
return new GenericResponse<>(
loggedInBookService.findBooks(request)
);
}
服务项目
@Cacheable("books")
public Page< Book> findBooks(BookRequest request) {
return bookService(request);
}
申请
@Setter
@Getter
@AllArgsConstructor(access = PRIVATE)
@NoArgsConstructor(access = PRIVATE)
public class BookRequest implements Serializable {
private String isbn;
private List<String> isbns;
private LocalDate bookAddedDateFrom;
private LocalDate bookAddedDateTo;
private boolean hasCopy = true;
}
我在第一个请求中将'hasCopy'设置为'true'时收到了正确的响应。然而,在随后的请求中,我收到了一个不正确的响应,表现得好像'hasCopy'被设置为'false'。
是什么导致了这个问题?
1条答案
按热度按时间44u64gxh1#
乍一看,我看到的
@Cacheable
注解的findBooks(:BookRequest)
服务方法的直接问题是,BookRequest
对象没有实现Object
equals(:Object)
和hashCode()
方法。有两件事你需要知道:
1.首先,Spring Framework的Cache Abstraction默认情况下使用
@Cacheable
注解方法的声明参数的参数作为该高速缓存条目的键,除非您通过使用key
属性或自定义KeyGenerator
另行指定。在您的示例中,
findBooks(..)
服务方法该高速缓存条目为:1.其次,由于
Cache
只不过是一个(美化的)Map
数据结构,因此equals(:Object)
和hashCode()
方法的实现非常重要。我没有看到您实际上在
BookRequest
对象上实现了equals(:Object)
和hashCode()
方法。由于您使用的是Lombok,因此只需在BookRequest
类上声明Lomboks的@EqualsAndHashCode
注解即可实现equals(:Object)
和hashCode()
。但是,
equals(:Object)
和hashCode()
方法必须为逻辑上相同的对象一致地返回相同的值。假设你的
BookRequest
有一个ISBN,并且ISBN唯一地标识了Book
,那么你可以通过以下操作来使用ISBN,而不是使用BookRequest
作为该高速缓存条目中的“键”:同样,请参阅参考文档中关于自定义键以及在
@Cacheable
注解属性中使用SpEL的内容,如key
,以了解更多详细信息。如果您没有启用Java compiler debug mode,则需要将
#bookRequest.isbn
替换为#a0.isbn
。即使
BookRequest
类上没有equals(:Object)
和hashCode()
方法实现,在@Cacheable
注解集上使用key
属性BookRequest
isbn
应该足够了。但是,只有当ISBN
始终存在于请求中时,这才有效(我怀疑可能不是)。另外,无论如何,覆盖并实现
Object
、equals(:Object)
和hashCode()
方法始终是一个好的做法。祝你好运!