2016-11-24 2 views
2

Nous avons une API REST, pour quelques commentaires. À l'heure actuelle, les plus intéressants URIs sont:Spring REST réutiliser requstmapping imbriqué

GET /products/1/comments    // get all comments of product 1 
GET /products/1/comments/5   // get the 5th comment of product 1 
GET /products/1/comments/5/user  // get the user of the 5th comment 
GET /products/1/comments/latest  // get the latest comment of product 1 
GET /products/1/comments/latest/user // get the user of the latest comment 

en plus, vous pouvez accéder directement à des commentaires

GET /comments/987     // get the comment with id 987 
GET /comments/987/user    // get the user of comment with id 987 

, nous avons deux @RestController:

@RestController 
@RequestMapping("/products/{productId}") 
public class ProductsCommentsResource { 

    @GetMapping(value = "/comments") 
    public ResponseEntity<?> getComments(@PathVariable Long productId){ 
     // get all products... 
    } 

    @GetMapping(value = "/comments/{commentNr}") 
    public ResponseEntity<?> getComment(@PathVariable Long productId, @PathVaraible Long commentNr){ 
     // get comment with number commentNr of product productId 
    } 

    @GetMapping(value = "/comments/{commentNr}/user") 
    public ResponseEntity<?> getCommentUser(@PathVariable Long productId, @PathVaraible Long commentNr){ 
     // get the user of comment with commentNr of productId 
    } 

    @GetMapping(value = "/comments/latest") 
    public ResponseEntity<?> getLatestComment(@PathVariable Long productId){ 
     // get latest commentNr and call getComment(productId, commentNr) 
    } 

    @GetMapping(value = "/comments/latest/user") 
    public ResponseEntity<?> getLatestCommentUser(@PathVariable Long productId){ 
     // get latest commentNr and call getCommentUser(productId, commentNr) 
    } 
} 

@RestController 
@RequestMapping("/comments") 
public class CommentsResource { 
    @GetMapping(value = "/{commentId}") 
    public ResponseEntity<?> getComment(@PathVaraible Long commentId){ 
     // get comment id commentId 
    } 

    @GetMapping(value = "/{commentId}/user") 
    public ResponseEntity<?> getCommentUser(@PathVaraible Long commendId){ 
     // get the user of comment with id commentId 
    } 
}  

Le latest est donc seulement mot-clé de remplacement pour "obtenir le dernier commentaireNr et appeler la méthode correspondante avec ce commentaire"

Ceci est juste un extrait et en plus de l'utilisateur, un commentaire a environ 30 sous-sous et sous-sous-ressources (y compris les méthodes POST, DELETE, etc.). Par conséquent, nous avons plus ou moins tout trois fois.

Alors, évidemment, nous devons améliorer cela, pour supprimer le code en double, etc. L'idée est de « résumer » les commentaires-ressources et la rendre réutilisable en utilisant le @RequestMapping annoté à la classe.

Nous avons pensé à un mechnism comme:

  • le /products/1/comments/latest/user est appelé
  • l'appel est intercepté et la « dernière » du produit 1 est résolu à l'CommentID
  • l'appel sera redirigé vers `` `/ commentaires/{commendId}/user

Ainsi, nous aurions besoin d'avoir quelque chose qui redirige - /products/1/comments/latest[what ever]-/comments/{commentId}[what ever] - /products/1/comments/5[what ever] également à /comments/{commentId}[what ever]

et/comments/{commentId} serait la seule implémentation.

Cependant, nous n'avons rien trouvé approprié dans la documentation de printemps ...

Répondre

4

Vous pouvez ajouter le préfixe de chemin d'URL supplémentaire dans votre contrôleur de @RequestMapping.

@RequestMapping(value = { "/products/{productId}", "/" }) 

Cela signifie que vous pouvez supprimer le contrôleur CommentsResource et vous serez en mesure d'accéder à la même ressource à:

/products/1/comments/5 

et à

/comments/5 

Par exemple, ici:

@GetMapping(value = "/comments/{commentNr}") 
    public ResponseEntity<?> getComment(@PathVariable Long productId, @PathVaraible Long commentNr){ 
     // get comment with number commentNr of product productId 
    } 

Le problème évident serait une variable de chemin productId. Si vous utilisez Java 8, cela peut être résolu assez facilement en utilisant Optional:

@GetMapping(value = "/comments/{commentNr}") 
public ResponseEntity<?> getComment(@PathVariable Optional<Long> productId, @PathVaraible Long commentNr){ 
    // get comment with number commentNr of product productId 
    // Check whether productId exists 
} 
+1

Merci. J'ai toujours pensé que les variables de chemin ne pouvaient pas être optionnelles. Je vais essayer – Indivon