我正在使用Spring-boot-starter-data-jpa,在我的RestController中我想返回新创建的对象的Location。有没有办法扭转@ RequestMapping而不是硬编码如何构建URL?
@RestController
@ExposesResourceFor(BookInstance.class)
public class BookInstanceController {
@RequestMapping(value="/bookInstances", method=RequestMethod.POST)
ResponseEntity<BookInstance> createBookInstance(@RequestBody BookInstance bookInstance){
BookInstance createdBookInstance = bookInstanceRepository.save(bookInstance);
return ResponseEntity.created(**reverseURL(createdBookInstance)**);
// return new ResponseEntity<BookInstance>(createdBookInstance, HttpStatus.CREATED);
// return createdBookInstance;
}
}
我总是看到人们在这个函数中硬编码他们的URL构造,这让我没有言语......
当然我在同一个类中也有一个GET函数(否则就没有任何东西可以反转)
@RequestMapping(value="/bookInstances/{id}", method=RequestMethod.GET)
ResponseEntity<?> findOne(@PathVariable("id") Long id){
BookInstance bookInstance = bookInstanceRepository.findOne(id);
if(bookInstance == null){
return ResponseEntity.notFound().build();
}
return new ResponseEntity<BookInstance>(bookInstance, HttpStatus.OK);
}
使用资源汇编程序的替代解决方案:
public class BookInstanceResource extends Resource<BookInstance> {
public BookInstanceResource(Book content, Link... links) {
super(content, links);
}
}
public class BookInstanceResourceAssembler extends ResourceAssemblerSupport<BookInstance, BookInstanceResource> {
public BookInstanceResourceAssembler() {
super(BookInstanceController.class, BookInstanceResource.class)
}
@Override
public BookInstanceResource toResource(BookInstance bookInstance) {
// linkTo requires the following static import:
// import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
ControllerLinkBuilder builder = linkTo(BookInstance.class).slash("bookInstances").slash(bookInstance);
return new BookInstanceResource(bookInstance,
builder.withSelfRel(),
builder.withRel("bookInstance");
}
}
在您的控制器类中:
@Autowired
private BookInstanceResourceAssembler resourceAssembler;
@GetMapping(value = "/bookInstances/{id}")
ResponseEntity findOne(@PathVariable("id") Long id) {
BookInstance bookInstance = bookInstanceRepository.findOne(id);
if(bookInstance == null){
return ResponseEntity.notFound().build();
}
BookInstanceResource resource = resourceAssembler.toResource(bookInstance);
return ResponseEntity.created(URI.create(resource.getLink("self").getHref()))
.body(resource);
}
我把它添加到我的班级解决了它:
@Autowired EntityLinks entityLinks;
并使用Spring的一些HATEOAS功能。
Link link = entityLinks.linkToSingleResource(BookInstance.class, createdBookInstance.getId()).expand();
return ResponseEntity.created(URI.create(link.getHref())).build();
注意:在上面的行中,在创建DB中的记录后,createdBookInstance只是返回对象。
由于其他解决方案与我的源代码不兼容,因此我很难找到返回新创建的实体访问API的URL的解决方案。我个人认为@EralpB解决方案很简单。但是,我遇到了SimpleEntityPlugin的一个问题,它在创建Link时在内部使用。
最后,我找到了简单代码剪切的解决方案,我不打算使用任何这样的Hateoas API。我不确定这个解决方案是否与Spring兼容,但我尝试使用SpringBoot-2.x版本。它对我来说很好。
@PostMapping("/students")
public ResponseEntity<Object> createStudent(@RequestBody Student student) {
Student savedStudent = studentRepository.save(student);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(savedStudent.getId()).toUri();
return ResponseEntity.created(location).build();
}
根据上面的例子,URL将像http://localhost:8080/students/1一样返回。这可能会因您的配置而异。
如果您需要在学生旁边和URL中的id之前添加任何额外路径,您可以直接在{id}声明之前进行硬编码,例如/ search / {id}。所以实际的URL看起来像http://localhost:8080/students/search/1
如果以防万一,您没有将学生配置为按ID搜索学生的一部分,并且您配置了一些其他路径来按ID访问学生,您可以使用以下代码仅加载上下文,路径例如http://localhost:8080并添加硬编码/加载属于uri。
URI location = ServletUriComponentsBuilder.fromCurrentContextPath().path("/search/{id}")
.buildAndExpand(newCase.getCaseId()).toUri();
根据上面的代码片段,返回的URL看起来像http://localhost:8080/search/1。您可以探索ServletUriComponentsBuilder下的不同方法。我希望这一点很清楚。