Spring Data Rest下如何用WebMvcLinkBuilder配合返回Optional的findById生成链接
问题根因
报错的核心原因是WebMvcLinkBuilder.methodOn在生成代理对象时,需要对目标方法的返回值做子类增强,而JpaRepository.findById返回的java.util.Optional是final类,无法被继承代理,因此触发了上述异常。
同时methodOn本身是为Spring MVC自定义Controller设计的工具,并不适配Spring Data REST自动暴露的Repository接口方法。
推荐解决方案:使用EntityLinks生成关联链接
Spring Data REST 自带了EntityLinks工具类,专门用于生成实体资源的标准链接,不需要硬编码路径,也无需调用Repository方法,完美适配你的需求:
import org.springframework.hateoas.EntityLinks; import org.springframework.context.annotation.Bean; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.server.RepresentationModelProcessor; import org.springframework.beans.factory.annotation.Autowired; // 先注入EntityLinks @Autowired private EntityLinks entityLinks; @Bean public RepresentationModelProcessor<EntityModel<Order>> orderProcessor() { return model -> { Order order = model.getContent(); if (order == null || order.getCustomerId() == null) { return model; } CustomerId customerId = new CustomerId(order.getTenantId(), order.getCustomerId()); // 直接生成Customer实体对应ID的资源链接 model.add(entityLinks.linkForItemResource(Customer.class, customerId).withRel("customer")); return model; }; }
备选方案:手动构造链接
如果你需要自定义路径规则,也可以直接用WebMvcLinkBuilder手动拼接路径,不需要依赖Repository方法:
@Bean public RepresentationModelProcessor<EntityModel<Order>> orderProcessor() { return model -> { Order order = model.getContent(); if (order == null || order.getCustomerId() == null) { return model; } CustomerId customerId = new CustomerId(order.getTenantId(), order.getCustomerId()); model.add(WebMvcLinkBuilder.linkTo(Customer.class) .slash("customers") .slash(customerId) .withRel("customer")); return model; }; }
两种方案都不需要查询Customer实体,仅会在Order资源的_links中添加customer关联链接,完全符合你的需求。
内容的提问来源于stack exchange,提问作者bmauter
相关产品推荐
相关产品推荐

