Spring REST重用嵌套的requstmapping

Ind*_*von 3 java rest spring api-design spring-mvc

我们有一个REST API,用于一些评论.目前,最有趣的URI是:

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
Run Code Online (Sandbox Code Playgroud)

此外,您还可以直接访问评论

GET /comments/987                    // get the comment with id 987
GET /comments/987/user               // get the user of comment with id 987
Run Code Online (Sandbox Code Playgroud)

所以,我们有两个@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
    }
}      
Run Code Online (Sandbox Code Playgroud)

latest因此只替换关键字为"本commentId得到最后commentNr并调用相应的方法"

这只是一个摘录,除了用户之外,评论还有大约30个子资源和子资源(包括POST,DELETE等方法).因此,我们或多或少都有三次.

因此,显然,我们需要改进这一点,删除重复的代码等.这个想法是"封装"注释资源,并通过使用@RequestMapping类中的注释使其可重用.

我们考虑过像以下一样的机制:

  • /products/1/comments/latest/user被称为
  • 该呼叫被截获,产品1的"最新"被解析为commentId
  • 调用将重定向到``/ comments/{commendId}/user

因此,我们需要有一些重定向- /products/1/comments/latest[what ever]/comments/{commentId}[what ever] - /products/1/comments/5[what ever]/comments/{commentId}[what ever]

和/ comments/{commentId}将是唯一的实现.

但是,我们在春季文档中找不到任何合适的内容......

Bra*_*zic 5

您可以在控制器中添加其他URL路径前缀@RequestMapping.

@RequestMapping(value = { "/products/{productId}", "/" })
Run Code Online (Sandbox Code Playgroud)

这意味着您可以删除CommentsResource控制器,并且您将能够访问相同的资源:

/products/1/comments/5
Run Code Online (Sandbox Code Playgroud)

并在

/comments/5
Run Code Online (Sandbox Code Playgroud)

例如,这里:

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

显而易见的问题是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
}
Run Code Online (Sandbox Code Playgroud)