Spring REST中的子资源

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring REST中的子资源相关的知识,希望对你有一定的参考价值。

我正在尝试构建Messenger应用程序。

我要从MessageResource调用CommentResource。

我想要单独的MessageResources和CommentResources。

我正在做这样的事情:

message resource.Java

@RestController
@RequestMapping("/messages")
public class MessageResource {

    MessageService messageService = new MessageService();

    @RequestMapping(value = "/{messageId}/comments")
    public CommentResource getCommentResource() {
        return new CommentResource();
    }
}

comment resource.Java

@RestController
@RequestMapping("/")
public class CommentResource {

    private CommentService commentService = new CommentService();

    @RequestMapping(method = RequestMethod.GET, value="/abc")
    public String test2() {
        return "this is test comment";
    }
}

我想要

http://localhost:8080/messages/1/comments/abc

返回“这是测试评论”。

任何的想法??

PS:简单来说,我想知道JAX-RS sub-resource中的spring-rest等效实现

答案

您的网址(http://localhost:8080/messages/1/comments/abc)表明评论嵌套在邮件中。您的控制器应如下所示:

@RestController
@RequestMapping("/messages")
public class MessageResource {

    @RequestMapping(value = "/{messageId}")
    public String getCommentResource(@PathVariable("messageId") String messageId) {
        //test
        return messageId;
    }

    @RequestMapping(value = "/{messageId}/comments/{commentsContent}")
    public String getCommentResource(
                      @PathVariable("messageId") String messageId, 
                      @PathVariable("commentsContent") String commentsContent) {
        //test
        return messageId + "/" + commentsContent;
    }
}

我不完全确定你想在MessageResource类中做什么,但想法就在那里。

Rest - HTTP methods

目前,这些用途是Get请求。但是,您应该考虑使用适当的Http方法:

  • 获取:阅读资源
  • 发布:创建资源
  • 放:更新
  • 删除:删除:)

看看这个:http://www.restapitutorial.com/lessons/httpmethods.html

Example with Post:

@RequestMapping(method=RequestMethod.POST, value = "/{messageId}/comments/{commentsContent}")
    public ResponseEntity<String> getCommentResource(
                                  @PathVariable("messageId") String messageId, 
                                  @RequestBody Comment comment) {
        //fetch the message associated with messageId
        //add the comment to the message
        //return success
        return new ResponseEntity<String>(HttpStatus.OK);
 }

Class names

另外,我个人会将这些类重命名为MessageController和CommentController。

Edit after comments - Split controllers

你可以直接拆分控制器(更接近你拥有的):

@RestController
@RequestMapping("/messages")
public class MessageResource {

    @RequestMapping(value = "/{messageId}")
    public String getCommentResource(@PathVariable("messageId") String messageId) {
        //test
        return messageId;
    }
}

@RestController
@RequestMapping("/messages")
public class CommentResource {

    @RequestMapping(value = "/{messageId}/comments/{commentsContent}")
    public String getCommentResource(
                      @PathVariable("messageId") String messageId, 
                      @PathVariable("commentsContent") String commentsContent) {
        //test
        return messageId + "/" + commentsContent;
    }
}
另一答案

您正在寻找的是JAX-RS实现,例如Jersey,并且被称为Sub-Resources。构建大型嵌入式API时,子资源是一个非常有用的功能。

Spring Boot默认休息实现不是JAX-RS而是SpringMVC。虽然可以在Spring Boot中使用Jersey,但尝试设置它有点涉及,并且在社区中似乎没有得到很好的使用/支持。

在旁注,DropWizard很棒!

另一答案

我也被迫从JAX-RS迁移到Spring-MVC。

我仍然在寻找一种优雅的方式,就像我使用JAX-RS一样。

我正在分享我尝试过的东西。

@RestController
@RequestMapping("parents")
public class ParentsController {

    @RequestMapping(method = RequestMethod.GET,
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<List<Parent>> read() {
    }

    @RequestMapping(method = RequestMethod.GET,
                    path = "/{id:\d+}",
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Parent> read(@PathVariable("id") final long id) {
    }
}

ChildrenController

@RestController
@RequestMapping("/parents/{parentId:\d+}/children")
public class ChildrenController {

    @RequestMapping(method = RequestMethod.GET,
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public List<Child> read(@PathVariable("parentId") final long parentId) {
    }

    @RequestMapping(method = RequestMethod.GET, path = "/{id:\d+}",
                    produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public Child read(@PathVariable("parentId") final long parentId,
                     @PathVariable("id") final long id) {
    }
}

我发现的两个问题,

@PathVariable不适用于田地。

我只是不能做@PathVariable("parentId") private long parentId;

ChildrenController的多重映射没有自由意志

JAX-RS的一个美妙之处在于我们可以将ChildrenController映射到不同的路径,甚至ChildrenController也有类级别的@Path

@Path("/children");
public class ChildrenResource {
}

@Path("/parents")
public class ParentsResource {

    @Path("/{id}/children")
    public ChildrenResource resourceChildren() {
    }
}


/children
/parents/{id}/children
另一答案

只需创建两个类并使用常量来引用子资源和父资源。这有助于在两个类之间建立链接,并使开发人员不再理解它们之间的关系。

所以:

@RequestMapping(value= MessageController.URL)
public class MessageController {
    public static final String URL= "/messages";
}

和:

@RequestMapping(value = MessageController.URL + "/{idMessage}/comments")
public class CommentController {

}

以上是关于Spring REST中的子资源的主要内容,如果未能解决你的问题,请参考以下文章

apache cxf rest服务中的Spring异常

Spring Data REST 的 QueryDSL 集成,用于查询实体中集合映射的子属性

Spring Boot 中 Rest 资源的 NotImplementedException

Spring Data REST

是否有适用于 JPA、spring-data、spring-data-rest 的通用 REST 查询语言

在 Spring Boot 的 DeferredResult REST 方法中使用 Semaphore 服务