![](/img/trans.png)
[英]REST Client Sub-resources return AbstractMethodError when invoked
[英]Sub-Resources in spring REST
我正在尝试构建信使应用程序。
我必须从 MessageResource 调用 CommentResource。
我想要单独的 MessageResources 和 CommentResources。
我正在做这样的事情:
消息资源.java
@RestController
@RequestMapping("/messages")
public class MessageResource {
MessageService messageService = new MessageService();
@RequestMapping(value = "/{messageId}/comments")
public CommentResource getCommentResource() {
return new CommentResource();
}
}
评论资源.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:简单来说就是想知道spring-rest
JAX-RS sub-resource
等价实现
在 Spring boot 中,我们可以使用@Autowired Spring 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.
您的 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;
}
}
我不完全确定您希望在 MessageResource 类中做什么,但想法就在那里。
目前,这些用途是 Get 请求。 但是,您应该考虑使用适当的 Http 方法:
看看这个: http : //www.restapitutorial.com/lessons/httpmethods.html
@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);
}
另外,我个人会将这些类重命名为 MessageController 和 CommentController。
您可以直接拆分控制器(更接近您拥有的):
@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 默认的 rest 实现不是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 {
}
您还可以将控制器拆分到不同的包中,也可以在包组织中显示此层次结构:
com.company.web.message.MessageController
com.company.web.message.comment.CommentController
消息控制器.java
@RestController
@RequestMapping(value = "/messages")
public class MessageController {
@Autowired
private MessagesService messageService;
}
注释控制器.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;
}
}
消息资源.java
@RestController
@RequestMapping("/messages")
public class MessageResource {
MessageService messageService = new MessageService();
// as usual messages related CRUD operations
}
评论资源.java
@RestController
@RequestMapping("messages/{messageId}/comments")
public class CommentResource {
private CommentService commentService = new CommentService();
@RequestMapping(method = RequestMethod.GET, value="/abc")
public String test2() {
return "this is test comment";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.