web-dev-qa-db-fra.com

Sous-ressources au printemps REST

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

12
prranay

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à.

Reste - méthodes HTTP

Pour l'instant, ces utilisations sont des requêtes Get. Vous devriez cependant envisager d'utiliser la méthode HTTP appropriée:

  • Get: lire une ressource
  • Poster: créer une ressource
  • Put: mise à jour
  • Supprimer: supprimer :)

Jetez un oeil à ceci: http://www.restapitutorial.com/lessons/httpmethods.html

Exemple avec 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);
 }

Noms de classe

De plus, je renommerais personnellement ces classes en MessageController et CommentController.

Editer après les commentaires - Contrôleurs divisés

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

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!

3
Paul Murphy

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;

Pas de volonté libre pour le mappage multiple pour 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
1
Jin Kwon

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 {

}
0
Dherik