J'essaie de créer une application de messagerie instantanée.
J'ai à appeler CommentResource de MessageResource.
Je veux séparer MessageResources et CommentResources.
Je fais quelque chose comme ça:
MessageResource.Java
@RestController
@RequestMapping("/messages")
public class MessageResource {
MessageService messageService = new MessageService();
@RequestMapping(value = "/{messageId}/comments")
public CommentResource getCommentResource() {
return new CommentResource();
}
}
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";
}
}
Je voudrais
http: // localhost: 8080/messages/1/comments/abc
pour renvoyer "c'est un commentaire test".
Une idée??
PS: Dans un simple mot, je veux savoir JAX-RS sub-resource
implémentation équivalente dans spring-rest
Votre URL ( http: // localhost: 8080/messages/1/comments/abc ) suggère que les commentaires sont imbriqués dans le message. Votre contrôleur devrait ressembler à ceci:
@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;
}
}
Je ne suis pas tout à fait sûr de ce que vous souhaitez faire dans votre classe MessageResource, mais l'idée est là.
Pour l'instant, ces utilisations sont des requêtes Get. Vous devriez cependant envisager d'utiliser la méthode HTTP appropriée:
Jetez un oeil à ceci: 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);
}
De plus, je renommerais personnellement ces classes en MessageController et CommentController.
Vous pouvez simplement diviser les contrôleurs (plus près de ce que vous aviez):
@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;
}
}
Ce que vous recherchez est pris en charge dans les implémentations JAX-RS
telles que Jersey et est appelé Sub-Resources
. Lors de la construction de grandes API imbriquées dans la nature, les sous-ressources sont une fonctionnalité extrêmement utile.
L'implémentation de repos par défaut de Spring Spring n'est pas un JAX-RS
mais une SpringMVC
. Bien qu'il soit possible d'utiliser Jersey dans Spring Boot, il est un peu compliqué d'essayer de le configurer et ne semble pas être bien utilisé/pris en charge par la communauté.
Sur une note de côté, DropWizard est génial!
Je suis également forcé de migrer de JAX-RS vers Spring-MVC.
Je cherche toujours un moyen élégant de le faire, comme je le fais avec JAX-RS.
Je partage ce que j'ai essayé.
@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) {
}
}
Et la 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) {
}
}
Deux problèmes que j'ai trouvés,
@PathVariable
n'est pas applicable sur les champs.Je ne peux tout simplement pas faire @PathVariable("parentId") private long parentId;
ChildrenController
La beauté de JAX-RS réside dans le fait que nous pouvons mapper ChildrenController
pour différents chemins, même si ChildrenController
possède un @Path
au niveau de la classe.
@Path("/children");
public class ChildrenResource {
}
@Path("/parents")
public class ParentsResource {
@Path("/{id}/children")
public ChildrenResource resourceChildren() {
}
}
/children
/parents/{id}/children
Créez simplement deux classes et utilisez un constant pour faire référence à la ressource enfants avec la ressource parent. Cela aide à établir un lien entre les deux classes et à permettre au développeur de comprendre leur relation.
Alors:
@RequestMapping(value= MessageController.URL)
public class MessageController {
public static final String URL= "/messages";
}
Et:
@RequestMapping(value = MessageController.URL + "/{idMessage}/comments")
public class CommentController {
}