Spring Web MVC不同方法中处理器方法参数相关问题
解决Spring WebMVC抽象基类中处理器参数传递问题
刚好之前处理过类似的Spring WebMVC抽象基类复用的场景,针对你遇到的「基类getAll方法调用抽象方法时的处理器参数问题」,给你几个实用的解决方案:
1. 直接在抽象方法中声明所需参数
Spring WebMVC会自动将请求中的参数(比如@RequestParam、HttpServletRequest这类上下文对象)注入到控制器方法中,你可以直接把这些参数传递给基类的抽象方法,子类实现时就能拿到这些参数进行业务处理。
示例代码:
abstract class BaseController<T> { @GetMapping("/all") fun getAll( @RequestParam("page", defaultValue = "0") page: Int, request: HttpServletRequest ): ResponseEntity<List<T>> { // 调用抽象方法并传递参数 val entities = fetchAllEntities(page, request) return ResponseEntity.ok(entities) } // 抽象方法明确声明需要的参数 protected abstract fun fetchAllEntities(page: Int, request: HttpServletRequest): List<T> } // 子类实现 @RestController class UserController : BaseController<User>() { override fun fetchAllEntities(page: Int, request: HttpServletRequest): List<User> { // 直接使用传入的page和request做业务逻辑 return userRepository.findAll(PageRequest.of(page, 10)).content } }
这种方式最直接,Spring会帮你完成所有参数解析和注入工作,子类只需要专注于业务实现。
2. 通过RequestContextHolder获取请求上下文
如果不想在抽象方法中显式传递太多参数,可以利用Spring提供的RequestContextHolder来获取当前请求的上下文信息,这样抽象方法不需要参数也能拿到请求相关数据。
示例代码:
abstract class BaseController<T> { @GetMapping("/all") fun getAll(@RequestParam("page", defaultValue = "0") page: Int): ResponseEntity<List<T>> { val entities = fetchAllEntities(page) return ResponseEntity.ok(entities) } protected abstract fun fetchAllEntities(page: Int): List<T> // 基类封装工具方法,子类可直接调用获取请求 protected fun getCurrentRequest(): HttpServletRequest { val attributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes return attributes.request } } // 子类实现 @RestController class UserController : BaseController<User>() { override fun fetchAllEntities(page: Int): List<User> { // 从基类工具方法获取当前请求 val currentRequest = getCurrentRequest() // 基于request做自定义处理,比如获取请求头、参数等 return userRepository.findAll(PageRequest.of(page, 10)).content } }
注意:这种方式仅在请求线程中有效,不要在异步任务或非请求触发的方法中调用,否则会抛出空指针异常。
3. 封装自定义参数对象
如果需要传递的参数较多,可以把这些参数封装成一个自定义对象,在基类的getAll方法中完成参数绑定后,再传递给抽象方法,让代码更简洁易维护。
示例代码:
// 自定义参数对象,封装分页相关参数 data class PageQueryParams( val page: Int = 0, val size: Int = 10 ) abstract class BaseController<T> { @GetMapping("/all") fun getAll( @RequestParam("page", defaultValue = "0") page: Int, @RequestParam("size", defaultValue = "10") size: Int ): ResponseEntity<List<T>> { val queryParams = PageQueryParams(page, size) val entities = fetchAllEntities(queryParams) return ResponseEntity.ok(entities) } protected abstract fun fetchAllEntities(params: PageQueryParams): List<T> } // 子类实现 @RestController class UserController : BaseController<User>() { override fun fetchAllEntities(params: PageQueryParams): List<User> { return userRepository.findAll(PageRequest.of(params.page, params.size)).content } }
后续如果需要新增参数,只需要修改PageQueryParams即可,不用修改抽象方法的签名,扩展性更好。
内容的提问来源于stack exchange,提问作者diesieben07
相关产品推荐
相关产品推荐

