Openfeign 分页

Last Modified: 2023/02/02

概述

本文讲述 Openfeign 是如何处理分页查询的。

实现

FeignClientsConfiguration 中注入了一个 PageableSpringEncoder,用支持分页查询:

@Bean
@ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
@ConditionalOnMissingBean
public Encoder feignEncoderPageable(ObjectProvider<AbstractFormWriter> formWriterProvider,
        ObjectProvider<HttpMessageConverterCustomizer> customizers) {
  PageableSpringEncoder encoder = new PageableSpringEncoder(
          springEncoder(formWriterProvider, encoderProperties, customizers)); 
          
  if (springDataWebProperties != null) {
    // 自定义分页参数
    encoder.setPageParameter(springDataWebProperties.getPageable().getPageParameter());
    encoder.setSizeParameter(springDataWebProperties.getPageable().getSizeParameter());
    encoder.setSortParameter(springDataWebProperties.getSort().getSortParameter());
  }
  return encoder;
}

从上面的代码可以看出,分页参数是可以自定的:

spring:
  data:
    web:
      pageable:
        page-parameter: pageNo
        default-page-size: 10
        size-parameter: limit

如果不配置,那么默认的 page-parameter 为 page,默认的 size-parameter 为 size。

PageableSpringEncoder 中的 encode 方法会对分页参数作出处理:

@Override
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
  if (supports(object)) {
    // 为了支持分页,object 参数得实现 Pageable
  	if (object instanceof Pageable) {
  	  Pageable pageable = (Pageable) object;
  	  if (pageable.isPaged()) {
  	    // 分页参数被转化为查询参数
  	    template.query(pageParameter, String.valueOf(pageable.getPageNumber()));
  	    template.query(sizeParameter, String.valueOf(pageable.getPageSize()));
  	  }
  	  if (pageable.getSort() != null) {
  	    applySort(template, pageable.getSort());
  	  }
  	} else if (object instanceof Sort) {
  	  Sort sort = (Sort) object;
  	  applySort(template, sort);
  	}
  } else {
    if (delegate != null) {
      delegate.encode(object, bodyType, template);
    } else {
      throw new EncodeException("PageableSpringEncoder does not support the given object " 
          + object.getClass()
    	  + " and no delegate was provided for fallback!");
    }
  }
}

PageableSpringEncoder 在 encode 的时候会将分页参数转化为请求 url 的查询参数,拿上面的配置来说,最后的请求 url 为:

http://xx.com?pageNo=1&limit=10

实战

@FeignClient(contextId = "remoteFileService", value = "file-service", fallbackFactory = RemoteFileFallbackFactory.class)
public interface RemoteFileService
{
  // 重点在于 hello1 方法的参数得是 Pageable 类型
  @GetMapping("hello1")
  public R<String> hello1(Pageable pageable);
}

注: Pageable 的完全限定类型为 org.springframework.data.domain.Pageable。

调用的地方,我们可以使用 org.springframework.data.domain.PageRequest 提供的方法构造 Pageable 对象:

Pageable pageable = PageRequest.of(1, 200);
R<String> hello = remoteFileService.hello1(pageable);
有问题吗?点此反馈!

温馨提示:反馈需要登录