2016-11-24 9 views
2

У нас есть API REST для некоторых комментариев. В настоящее время наиболее интересные URIs являются:Повторное использование Spring REST вложенных requstmapping

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 

кроме того, вы можете получить прямой доступ комментарии

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

так, у нас есть два @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 
    } 
}  

Таким образом, latest является лишь change-keyword for "получить последний комментарийNr и вызвать соответствующий метод с этим комментарием"

Это всего лишь выдержка, и в дополнение к пользователю комментарий содержит около 30 суб-и суб-ресурсов (включая методы POST, DELETE и т. Д.). Поэтому у нас есть более-менее все три раза.

Таким образом, очевидно, нам нужно улучшить это, чтобы удалить дубликаты кода и т.д. Идея заключается в том, чтобы «инкапсулировать» в комментарии-ресурсы и сделать его повторного использования с помощью @RequestMapping аннотированный в классе.

Мы думали о mechnism как:

  • в /products/1/comments/latest/user называется
  • вызов перехватывается и «последний» продукта 1 разрешен к CommentID
  • вызов будет перенаправлять `` `/ комментарии/{commendId}/пользователь

Таким образом, мы должны были бы иметь что-то, что перенаправляет - /products/1/comments/latest[what ever] к /comments/{commentId}[what ever] - /products/1/comments/5[what ever] также /comments/{commentId}[what ever]

и/комментарии/{commentId} будут единственной реализацией.

Однако, мы не нашли ничего подходящего в пружинных документах ...

ответ

4

Вы можете добавить дополнительный префикс URL пути в вашем контроллере @RequestMapping.

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

Это означает, что вы можете удалить CommentsResource контроллер, и вы будете иметь возможность получить доступ к этому ресурсу по адресу:

/products/1/comments/5 

и на

/comments/5 

Например, здесь:

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

Очевидной проблемой будет переменная пути productId. Если вы используете Java 8, это можно решить довольно просто, используя 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

Спасибо. Всегда считал, что переменные пути не могут быть дополнительными. Я дам ему попробовать – Indivon