Spring中能否用内部类声明端点?如何拆分控制器并获取路径变量?
Spring控制器拆分与内部类使用问题解答
问题背景
我需要优化控制器结构,将一个包含大量方法的QueueController拆分为QueueController和MessageController两个独立控制器。拆分后MessageController的@RequestMapping设为"/queues/{queue}/messages",需要获取其中的{queue}路径变量。尝试用内部类组织控制器时,调用queues端点出现404错误,现咨询两个问题:
- 是否可以使用内部类来组织Spring控制器?
- 能否访问控制器注解中声明的路径变量?
原控制器代码
@RestController @RequestMapping("/queues") class QueueController { @GetMapping(value = "/") fun index() = "index" @PostMapping(value = "/") fun store() = "store queue" @GetMapping(value = "/{queue}/messages") fun findMessagesByQueue(@PathVariable("queue") queue: String) = "messages from $queue" @PostMapping(value = "/{queue}/messages") fun storeMessage(@PathVariable("queue") queue: String) = "store message" }
拆分后的控制器代码
@RestController @RequestMapping("/queues") class QueueController { @GetMapping("/") fun index() = "index" // ... } @RestController @RequestMapping("/queues/{queue}/messages") class MessageController { @GetMapping("/") fun index() = "how to access que $queue value?" // ... }
内部类尝试的代码
@RestController @RequestMapping("/queues/") class Controller { // map this controller to an endpoint? how? inner class Queues {} // map this controller to an endpoint? how? inner class Messages {} }
问题解答
1. 是否可以使用内部类来组织Spring控制器?
可以,但内部类必须是静态的(Kotlin中不要用inner class,因为inner类会持有外部类引用,Spring无法实例化非静态内部类作为控制器)。
正确的做法是给内部类单独添加@RestController和@RequestMapping注解,并且将其声明为静态类(Kotlin中默认内部类就是静态的,无需额外关键字)。示例代码如下:
class Controller { @RestController @RequestMapping("/queues") class Queues { @GetMapping("/") fun index() = "index" } @RestController @RequestMapping("/queues/{queue}/messages") class Messages { @GetMapping("/") fun index(@PathVariable("queue") queue: String) = "messages from $queue" } }
你之前的代码出现404,是因为内部类没有添加控制器相关注解,Spring无法识别它们为控制器,自然不会映射端点。另外,外部类不需要加@RestController,真正的控制器是内部的静态类。
2. 能否访问控制器注解中声明的路径变量?
完全可以。在控制器方法中通过@PathVariable注解即可获取类级别@RequestMapping里的路径变量,Spring会自动完成变量传递。
修正后的MessageController代码如下:
@RestController @RequestMapping("/queues/{queue}/messages") class MessageController { @GetMapping("/") fun index(@PathVariable("queue") queue: String) = "messages from $queue" @PostMapping("/") fun store(@PathVariable("queue") queue: String) = "store message for $queue" }
内容的提问来源于stack exchange,提问作者Rafa Acioly
相关产品推荐
相关产品推荐

