解决 Webflux 中的 Pageable
Posted
技术标签:
【中文标题】解决 Webflux 中的 Pageable【英文标题】:Resolving Pageable in Webflux 【发布时间】:2018-11-16 17:34:42 【问题描述】:我花了很多时间在 Webflux 中寻找关于 Pageable 的解决方案,不幸的是,在撰写本文时,Webflux 不支持 Pageable,所以我想出了一个解决方案,这就是我已经实现的。这是在 Spring Boot 中解决 Webflux 控制器/资源中的 Pageable 和 Sort 类型的 hacky 解决方案。
这是解决方案:(我知道它可能很难看,但您可以在 Spring 团队解决问题之前使用它,我们正在为此努力。Spring Jira
另外,要点在这里:Github
更新1:你也可以找到文章here in medium
版本:
Spring Boot: 2.0.2.RELEASE
Gradle Kotlin: 1.2.41
请随时给我提示以改进它。 (代码是 Kotlin)
@Configuration
class PageableSerializer
@Bean
@ConditionalOnMissingBean
fun pageableCustomizer(properties: SpringDataWebProperties): PageableHandlerMethodArgumentResolverCustomizer
return PageableHandlerMethodArgumentResolverCustomizer resolver ->
val pageable = properties.pageable
resolver.setPageParameterName(pageable.pageParameter)
resolver.setSizeParameterName(pageable.sizeParameter)
resolver.setOneIndexedParameters(pageable.isOneIndexedParameters)
resolver.setPrefix(pageable.prefix)
resolver.setQualifierDelimiter(pageable.qualifierDelimiter)
resolver.setFallbackPageable(PageRequest.of(0, pageable.defaultPageSize))
resolver.setMaxPageSize(pageable.maxPageSize)
@Bean
@ConditionalOnMissingBean
fun sortCustomizer(properties: SpringDataWebProperties): SortHandlerMethodArgumentResolverCustomizer
return SortHandlerMethodArgumentResolverCustomizer resolver ->
resolver.setSortParameter(properties.sort.sortParameter)
@Bean
fun pageableHandler(pageableResolver: Optional<PageableHandlerMethodArgumentResolverCustomizer>, sortHandler: SortHandlerMethodArgumentResolver, reactiveAdapterRegistry: ReactiveAdapterRegistry): PageableHandlerMethodArgumentResolver
val handler = PageableHandlerMethodArgumentResolver(sortHandler)
pageableResolver.ifPresent c -> c.customize(handler)
return handler
@Bean
fun sortHandler(sortResolver: Optional<SortHandlerMethodArgumentResolverCustomizer>): SortHandlerMethodArgumentResolver
val handler = SortHandlerMethodArgumentResolver()
sortResolver.ifPresent c -> c.customize(handler)
return handler
并注册处理程序:
@Component
class PageableResolver(registry: ReactiveAdapterRegistry, private val resolver: PageableHandlerMethodArgumentResolver) : HandlerMethodArgumentResolverSupport(registry)
override fun resolveArgument(parameter: MethodParameter, bindingContext: BindingContext, exchange: ServerWebExchange): Mono<Any>
return Mono.just(resolver.resolveArgument(parameter, null, MockNative(exchange.request.queryParams), null))
override fun supportsParameter(parameter: MethodParameter): Boolean
return this.resolver.supportsParameter(parameter)
private class MockNative(private val parameters: MultiValueMap<String, String>) : NativeWebRequest
override fun getParameter(paramName: String): String?
return this.parameters.getFirst(paramName)
override fun getParameterValues(paramName: String): Array<String>?
return this.parameters[paramName]?.toTypedArray()
override fun isUserInRole(role: String): Boolean
return false
override fun getRemoteUser(): String?
return null
override fun getLocale(): Locale
return Locale.getDefault()
override fun getParameterMap(): MutableMap<String, Array<String>>
return mutableMapOf()
override fun getSessionId(): String
return ""
override fun getAttributeNames(scope: Int): Array<String>
return arrayOf()
override fun registerDestructionCallback(name: String, callback: Runnable, scope: Int)
override fun resolveReference(key: String): Any?
return null
override fun getHeaderValues(headerName: String): Array<String>?
return null
override fun getUserPrincipal(): Principal?
return null
override fun getDescription(includeClientInfo: Boolean): String
return ""
override fun getSessionMutex(): Any
return ""
override fun getNativeResponse(): Any?
return null
override fun <T : Any?> getNativeResponse(requiredType: Class<T>?): T?
return null
override fun getParameterNames(): MutableIterator<String>
return mutableListOf<String>().iterator()
override fun getNativeRequest(): Any
return ""
override fun <T : Any?> getNativeRequest(requiredType: Class<T>?): T?
return null
override fun removeAttribute(name: String, scope: Int)
override fun getHeader(headerName: String): String?
return null
override fun getContextPath(): String
return ""
override fun checkNotModified(lastModifiedTimestamp: Long): Boolean
return false
override fun checkNotModified(etag: String): Boolean
return false
override fun checkNotModified(etag: String?, lastModifiedTimestamp: Long): Boolean
return false
override fun getHeaderNames(): MutableIterator<String>
return mutableListOf<String>().iterator()
override fun getAttribute(name: String, scope: Int): Any?
return null
override fun setAttribute(name: String, value: Any, scope: Int)
override fun isSecure(): Boolean
return false
【问题讨论】:
【参考方案1】:见ReactivePageableHandlerMethodArgumentResolver类
以WebFluxConfigure
为例:
@Configuration
@ConditionalOnClass(EnableWebFlux.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class WebfluxConfig implements WebFluxConfigurer
@Override
public void configureArgumentResolvers(ArgumentResolverConfigurer configurer)
configurer.addCustomResolver(new ReactivePageableHandlerMethodArgumentResolver());
【讨论】:
是的,这个是经过很长的github问题讨论后最近添加的,谢谢提及 我不确定这个是否像addCustomResolver
需要 org.springframework.messaging.handler.invocation.reactive.HandlerMethodArgumentResolver
但 ReactivePageableHandlerMethodArgumentResolver
是 org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver
以上是关于解决 Webflux 中的 Pageable的主要内容,如果未能解决你的问题,请参考以下文章