代码之家  ›  专栏  ›  技术社区  ›  EralpB

Spring获取到实体的链接

  •  2
  • EralpB  · 技术社区  · 8 年前

    我使用的是Spring boot starter data jpa,在我的RestController中,我想返回新创建对象的位置。是否有一种方法可以逆转@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);
        }
    
    4 回复  |  直到 7 年前
        1
  •  4
  •   Nallamachu    6 年前

    我通过在课堂上添加以下内容解决了这个问题:

    @Autowired EntityLinks entityLinks;
    

    并使用Spring的一些HATEOAS特性。

    Link link = entityLinks.linkToSingleResource(BookInstance.class, createdBookInstance.getId()).expand();
    return ResponseEntity.created(URI.create(link.getHref())).build();
    

    注: 在上面的行中,CreatedBookinInstance只是在DB中创建记录后返回的对象。

        2
  •  3
  •   Nallamachu    6 年前

    由于其他解决方案与我的源代码不兼容,我一直在努力寻找返回新创建的实体访问API的URL的解决方案。就我个人而言,我觉得@EralpB解决方案很简单。但是,我在创建链接时在内部使用SimpleEntityPlugin时遇到了一个问题。

    最后,我找到了一个简单代码被剪掉的解决方案,我不打算使用任何这样的方法 哈提奥斯 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 .我希望这会很清楚。

        3
  •  2
  •   Marc Tarin    6 年前

    使用资源汇编程序的替代解决方案:

    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);
    }
    
        4
  •  0
  •   Lubo    5 年前

    要轻松获得正确的资源链接,您应该使用以下答案 https://stackoverflow.com/a/41956064/11152683 .

    返回 不仅仅是位置 而且 新创建的资源 ,您可以采取以下方法:

    import lombok.RequiredArgsConstructor;
    import org.springframework.data.rest.webmvc.PersistentEntityResource;
    import org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler;
    import org.springframework.data.rest.webmvc.RepositoryRestController;
    import org.springframework.hateoas.Link;
    import org.springframework.hateoas.server.EntityLinks;
    import org.springframework.hateoas.server.ExposesResourceFor;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import sk.qpp.qaron.user.repository.QaronUser;
    
    import java.net.URI;
    
    @RepositoryRestController
    @ExposesResourceFor(BookInstance.class)
    @RequiredArgsConstructor // lombok thing, autoviring all final attributes through ctor
    public class BookInstanceController {
        private final EntityLinks entityLinks;
    
        @RequestMapping(value="/bookInstances", method= RequestMethod.POST)
        ResponseEntity<Object> createBookInstance(@RequestBody BookInstance bookInstance, PersistentEntityResourceAssembler resourceAssembler){
            // save to database
            final BookInstance createdBookInstance = bookInstanceRepository.save(bookInstance);
    
            final PersistentEntityResource newEntityResource = resourceAssembler.toModel(createdBookInstance);
            Link link = entityLinks.linkToItemResource(QaronUser.class, createdBookInstance.getId()).expand();
            return ResponseEntity
                    .created(URI.create(link.getHref()))
                    .body(newEntityResource);
        }
    }
    

    请注意,此示例正在使用 @RepositoryRestController 而不是 @RestController .这对布线至关重要 PersistentEntityResourceAssembler 没有得到 java.lang.IllegalArgumentException: entities is marked non-null but is null .