解决 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.HandlerMethodArgumentResolverReactivePageableHandlerMethodArgumentResolverorg.springframework.web.reactive.result.method.HandlerMethodArgumentResolver

以上是关于解决 Webflux 中的 Pageable的主要内容,如果未能解决你的问题,请参考以下文章

webflux解决get请求中文乱码问题

webflux解决get请求中文乱码问题

webflux解决get请求中文乱码问题

webflux解决get请求中文乱码问题

Spring WebFlux WebClient - 如何解决 400 错误请求

Spring Webflux Security 中的角色层次结构