2016-11-24 203 views
2

我們有一個REST API,用於一些評論。目前,最有趣的URI是:Spring REST重用嵌套的請求映射

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被替換關鍵字爲「獲取最後評論Nr並用此評論ID調用相應的方法」

這只是一個摘錄,除了用戶,評論還有大約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]

和/ comments/{commentId}將是唯一的實現。

但是,我們並沒有找到合適的春天文檔什麼...

回答

4

你可以在你的控制器的@RequestMapping添加額外的URL路徑前綴。

@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