java spring REST 中的子资源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40328835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:07:32  来源:igfitidea点击:

Sub-Resources in spring REST

javarestspring-mvcspring-bootrequest-mapping

提问by prranay

I'm trying to build messanger app.

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

I've to call CommentResource from MessageResource.

我必须从 MessageResource 调用 CommentResource。

I want separate MessageResources and CommentResources.

我想要单独的 MessageResources 和 CommentResources。

I'm doing something like this :

我正在做这样的事情:

MessageResource.java

消息资源.java

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

    MessageService messageService = new MessageService();

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

CommentResource.java

评论资源.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";
    }
}

I want

我想

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

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

to return "this is test comment".

返回“这是测试评论”。

Any Idea??

任何的想法??

PS: In a simple word, I want to know JAX-RS sub-resourceequivalent implementation in spring-rest

PS:简单来说,我想知道JAX-RS sub-resourcespring-rest

回答by Tapan

In Spring boot, we can implement JAX-RS subresource concept using @AutowiredSpring Concept. Create an object of your child resource class and Spring will initialize at runtime and return that object. Don't create an Object manually. like: Above mention scenario

在 Spring boot 中,我们可以使用@AutowiredSpring Concept实现 JAX-RS 子资源概念。创建子资源类的对象,Spring 将在运行时初始化并返回该对象。不要手动创建对象。像:上面提到的场景

 - MessageResource.java

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

    MessageService messageService = new MessageService();
    @Autowired
    @Qualifier("comment")
    CommentResource comment;

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

 - CommentResource.java

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

    private CommentService commentService = new CommentService();

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



Now it will work like sub-resource
http://localhost:8080/messages/1/comments/abc

You can send any type of request.

回答by alexbt

Your url (http://localhost:8080/messages/1/comments/abc) suggests that comments are nested in the message. Your controller should look like this:

您的 url ( 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;
    }
}

I'm not entirely sure what you wish to do in your MessageResource class, but the idea is there.

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

Rest - HTTP methods

休息 - HTTP 方法

For now, these use are Get requests. You should however consider using the appropriate Http Method:

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

  • Get: read a resource
  • Post: create a resource
  • Put: update
  • Delete: delete :)
  • 获取:读取资源
  • 帖子:创建资源
  • 放置:更新
  • 删除:删除 :)

Take a look at this: http://www.restapitutorial.com/lessons/httpmethods.html

看看这个: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

班级名称

Also, I would personally rename these classes to MessageController and CommentController.

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

Edit after comments - Split controllers

评论后编辑 - 拆分控制器

You can just literally split the controllers (closer to what you had):

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

@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;
    }
}

回答by Paul Murphy

What you are looking for is supported in JAX-RSimplementations such as Jerseyand is called Sub-Resources. When building large APIs which become nested in nature, sub resources are an extremly useful feature.

您正在寻找的内容在JerseyJAX-RS实现中得到支持,并被称为. 在构建本质上嵌套的大型 API 时,子资源是一个非常有用的功能。Sub-Resources

Spring Boot default rest implementation is not a JAX-RSbut SpringMVC. Whilst it is possible to use Jersey in Spring Boot, it's a bit involved trying to set it up, and doesn't appear to be well used/supported in the community.

Spring Boot 默认的 rest 实现不是一个JAX-RSbut SpringMVC。虽然可以在 Spring Boot 中使用 Jersey,但尝试设置它有点复杂,并且在社区中似乎没有得到很好的使用/支持。

On a side note, DropWizardis awesome!

顺便说一句DropWizard很棒!

回答by Jin Kwon

I'm also being, forcedly, migrated from JAX-RS to Spring-MVC.

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

I'm still looking for an elegant way to do this just like I do with JAX-RS.

我仍在寻找一种优雅的方式来做到这一点,就像我对 JAX-RS 所做的那样。

I'm sharing what I've tried.

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

@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) {
    }
}

And the ChildrenController.

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) {
    }
}

Two problems I've found,

我发现了两个问题,

@PathVariableis not applicable on fields.

@PathVariable不适用于字段。

I just can't do @PathVariable("parentId") private long parentId;

我就是做不到 @PathVariable("parentId") private long parentId;

No free will for multiple mapping for ChildrenController

没有自由意志进行多重映射 ChildrenController

A beauty of JAX-RS is that we can map ChildrenControllerfor different paths like even the ChildrenControllerhas a class-level @Pathwith it.

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

回答by Dherik

Just create two classes and use a constantto refer the children resource with parent resource. This helps to make a link between the two classes and make the developer understand the relationship between them.

只需创建两个类并使用一个常量来引用带有父资源的子资源。这有助于在两个类之间建立联系,并使开发人员了解它们之间的关系。

So:

所以:

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

And:

和:

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

}

You can also split the controllers in different packages, showing this hierarchy in your package organization too:

您还可以将控制器拆分为不同的包,在您的包组织中也显示此层次结构:

com.company.web.message.MessageController
com.company.web.message.comment.CommentController 

回答by PraKhar

MessagesController.java

消息控制器.java

@RestController
@RequestMapping(value = "/messages")
public class MessageController {

    @Autowired
    private MessagesService messageService;

}

CommentController.java

注释控制器.java

@RestController
@RequestMapping("/messages/{messageId}/comments")
public class CommentController {


    @GetMapping
    public List<Comment> getComments(@PathVariable("messageId") Long messageId) {
        System.out.println("Get "+messageId);

        return null;
    }

}