文章目录
遇到问题
最近在学习《Spring实战》,学习到第六章的Spring Data端点添加自定义的超链接
时遇到了一个奇怪的问题。
当我向http://localhost:8080/api/tacos
发起请求时,发生了如下的错误:
{
"cause": null,
"message": "class org.springframework.data.rest.webmvc.PersistentEntityResource cannot be cast to class org.springframework.hateoas.PagedModel (org.springframework.data.rest.webmvc.PersistentEntityResource and org.springframework.hateoas.PagedModel are in unnamed module of loader 'app')"
}
而我只是将第一段代码替换为了替换为了第二段代码。而且第二段的Lambda表达式还是IDEA自动替换的。
第一段代码
@Bean
public RepresentationModelProcessor<PagedModel<EntityModel<Taco>>> tacoProcessor(EntityLinks links) {
return new RepresentationModelProcessor<PagedModel<EntityModel<Taco>>>() {
@Override
public PagedModel<EntityModel<Taco>> process(PagedModel<EntityModel<Taco>> resource) {
resource.add(
links.linkFor(Taco.class)
.slash("recent")
.withRel("recents"));
return resource;
}
};
}
第二段代码:
@Bean
public RepresentationModelProcessor<PagedModel<EntityModel<Taco>>> tacoProcessor(EntityLinks links) {
return resource -> {
resource.add(
links.linkFor(Taco.class)
.slash("recent")
.withRel("recents"));
return resource;
};
}
不太明白为什么将其使用Lambda替换以后请求同样的地址却会发生这样的问题。使用匿名内部类的形式的时候请求http://localhost:8080/api/tacos
则能正常返回数据。
由于这个问题发生的得有些莫名其妙,我先记录在此,期待大佬解答。
详细代码如下:位于spring-in-action-5-samples-master/ch06
章节
我的代码仓库
学习过程中的问题总结
接着我再回顾一下学习《Spring 实战》这本书时一路上遇到的问题。
由于原文用的Spring Boot的版本时2.0.4.RELEASE
。使用这个版本的Spring Boot则会发生如下问题
详情可以见我的另一篇博客:
Maven中依赖的优先级问题
原因是因为org.hibernate.validator:hibernate-validator:jar:6.0.11.Final
这个包有些问题,建议更新到更高的版本。
然后我就将Spring Boot的版本提高到了2.2.6.RELEASE
在该版本的Spring Boot中hibernate-validator
的版本提高到了6.0.18Final
则没有上述的问题,
但是不幸的是,学习到了第六章使用Spring HATEOAS
时高版本的Spring Boot却带来了很多问题。
书上使用的是2.0.4.RELEASE
这个版本的Spring Boot对应是Spring HATEOAS 0.25
。
而2.2.6.RELEASE
版本的Spring Boot对应的则是Spring HATEOAS 1.0.4
的版本。
不幸的是,从0.25变到1.0.4,Spring HATEOAS的API发生了很大改变,0.25版本中的Spring HATEOAS的很多API,对应到1.0.4版本的Spring HATEOAS,名字都已经发生了很大的改变,用法也有些区别。
Spring HATEOAS 0.25中的API | 对应 | Spring HATEOAS 1.0.4中的APT |
---|---|---|
ResourceSupport | 对应 | RepresentationModel |
Resource | 对应 | EntityModel |
Resources | 对应 | CollectionModel |
PagedResources | 对应 | PageModel |
ResourceAssembler | 对应 | RepresentationModelAssembler |
ResourceAssembler中的toResource(…),toResources(…) | 对应 | RepresentationModelAssembler中的toModel(…)和toCollectionModel(…) |
除此之外:
-
RepresentationModel.getLinks()现在公开了一个Links实例(通过List),该实例公开了其他API,以Links使用各种策略来连接和合并不同的实例。同样,它已经变成了自绑定的泛型类型,以允许向实例添加链接的方法返回实例本身。
-
LinkDiscovererAPI已移动到client包。
-
在LinkBuilder和EntityLinksAPI已经被移到了server包。
-
ControllerLinkBuilder已移入server.mvc,不推荐使用替换WebMvcLinkBuilder。
-
RelProvider已重命名为LinkRelationProvider并返回LinkRelation实例,而不是String。
-
VndError已移至mediatype.vnderror套件。
因此原书中的如下代码应该进行修改:
package tacos.web.api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.PagedResources;
import org.springframework.hateoas.Resource;
import org.springframework.hateoas.ResourceProcessor;
import tacos.Taco;
@Configuration
public class SpringDataRestConfiguration {
@Bean
public ResourceProcessor<PagedResources<Resource<Taco>>>
tacoProcessor(EntityLinks links) {
return new ResourceProcessor<PagedResources<Resource<Taco>>>() {
@Override
public PagedResources<Resource<Taco>> process(
PagedResources<Resource<Taco>> resource) {
resource.add(
links.linkFor(Taco.class)
.slash("recent")
.withRel("recents"));
return resource;
}
};
}
}
修改为如下:
package tacos.web.api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.PagedModel;
import org.springframework.hateoas.server.EntityLinks;
import org.springframework.hateoas.server.RepresentationModelProcessor;
import tacos.Taco;
@Configuration
public class SpringDataRestConfiguration {
@Bean
public RepresentationModelProcessor<PagedModel<EntityModel<Taco>>> tacoProcessor(EntityLinks links) {
return new RepresentationModelProcessor<PagedModel<EntityModel<Taco>>>() {
@Override
public PagedModel<EntityModel<Taco>> process(PagedModel<EntityModel<Taco>> resource) {
resource.add(
links.linkFor(Taco.class)
.slash("recent")
.withRel("recents"));
return resource;
}
};
}
}