JBC*_*BCP 24 spring spring-mvc spring-data spring-data-rest spring-hateoas
我正在尝试做一些我认为应该非常简单的事情.我有一个Question对象,设置有spring-boot,spring-data-rest和spring-hateoas.所有的基础工作都很好.我想添加一个自定义控制器,它返回一个List<Question>与我Repository的/questions网址完全相同的格式,以便两者之间的响应兼容.
这是我的控制器:
@Controller
public class QuestionListController {
@Autowired private QuestionRepository questionRepository;
@Autowired private PagedResourcesAssembler<Question> pagedResourcesAssembler;
@Autowired private QuestionResourceAssembler questionResourceAssembler;
@RequestMapping(
value = "/api/questions/filter", method = RequestMethod.GET,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody PagedResources<QuestionResource> filter(
@RequestParam(value = "filter", required = false) String filter,
Pageable p) {
// Using queryDSL here to get a paged list of Questions
Page<Question> page =
questionRepository.findAll(
QuestionPredicate.findWithFilter(filter), p);
// Option 1 - default resource assembler
return pagedResourcesAssembler.toResource(page);
// Option 2 - custom resource assembler
return pagedResourcesAssembler.toResource(page, questionResourceAssembler);
}
}
Run Code Online (Sandbox Code Playgroud)
选项1:依靠提供的 SimplePagedResourceAssembler
此选项的问题是没有必要_links呈现.如果有一个修复,这将是最简单的解决方案.
选项2:实现我的开放资源汇编程序
这个选项的问题是QuestionResourceAssembler根据Spring-Hateoas文档实现导致QuestionResource最终成为近似重复的路径Question,然后汇编器需要在两个对象之间手动复制数据,我需要构建所有相关_links的手工.这似乎是浪费了很多精力.
该怎么办?
我知道Spring已经生成了代码,以便在导出时执行所有这些操作QuestionRepository.有什么方法可以利用该代码并使用它,以确保我的控制器的输出是无缝的,可以与生成的响应互换?
小智 24
我找到了一种完全模仿Spring Data Rest行为的方法.诀窍在于使用PagedResourcesAssembler和参数注入的实例的组合PersistentEntityResourceAssembler.只需按如下方式定义控制器......
@RepositoryRestController
@RequestMapping("...")
public class ThingController {
@Autowired
private PagedResourcesAssembler pagedResourcesAssembler;
@SuppressWarnings("unchecked") // optional - ignores warning on return statement below...
@RequestMapping(value = "...", method = RequestMethod.GET)
@ResponseBody
public PagedResources<PersistentEntityResource> customMethod(
...,
Pageable pageable,
// this gets automatically injected by Spring...
PersistentEntityResourceAssembler resourceAssembler) {
Page<MyEntity> page = ...;
...
return pagedResourcesAssembler.toResource(page, resourceAssembler);
}
}
Run Code Online (Sandbox Code Playgroud)
这要归功于PersistentEntityResourceAssemblerArgumentResolverSpring 的存在,Spring会PersistentEntityResourceAssembler为你注入它.结果正是您对其中一个存储库查询方法的期望!
关于这个老问题的更新答案:你现在可以用一个 PersistentEntityResourceAssembler
在你的@RepositoryRestController里面:
@RequestMapping(value = "somePath", method = POST)
public @ResponseBody PersistentEntityResource postEntity(@RequestBody Resource<EntityModel> newEntityResource, PersistentEntityResourceAssembler resourceAssembler)
{
EntityModel newEntity = newEntityResource.getContent();
// ... do something additional with new Entity if you want here ...
EntityModel savedEntity = entityRepo.save(newEntity);
return resourceAssembler.toResource(savedEntity); // this will create the complete HATEOAS response
}
Run Code Online (Sandbox Code Playgroud)
我相信我已经以相当简单的方式解决了这个问题,尽管它本来可以更好地记录下来。
在阅读了 的实现之后,SimplePagedResourceAssembler我意识到混合解决方案可能会起作用。提供的Resource<?>类可以正确呈现实体,但不包含链接,因此您所需要做的就是添加它们。
我的QuestionResourceAssembler实现如下所示:
@Component
public class QuestionResourceAssembler implements ResourceAssembler<Question, Resource<Question>> {
@Autowired EntityLinks entityLinks;
@Override
public Resource<Question> toResource(Question question) {
Resource<Question> resource = new Resource<Question>(question);
final LinkBuilder lb =
entityLinks.linkForSingleResource(Question.class, question.getId());
resource.add(lb.withSelfRel());
resource.add(lb.slash("answers").withRel("answers"));
// other links
return resource;
}
}
Run Code Online (Sandbox Code Playgroud)
完成后,在我的控制器中我使用了上面的选项 2:
return pagedResourcesAssembler.toResource(page, questionResourceAssembler);
Run Code Online (Sandbox Code Playgroud)
这工作得很好,而且代码不多。唯一的麻烦是您需要为您需要的每个参考手动添加链接。
| 归档时间: |
|
| 查看次数: |
6935 次 |
| 最近记录: |