使用 Pageable 进行分页的 Micronaut 控制器

Micronaut controller with pagination using Pageable

我正在尝试使用带分页功能的 Micronaut 控制器。 Micronaut-Data 有 this Spring inspired way to access the repositories using the Pageable class and returning a Page

当你想显示这个分页数据时,问题就来了。我无法创建带有分页的控制器调用。这里我有一个简单的控制器:

    @Controller
    public class PageableController {

        private static final Logger LOGGER = LoggerFactory.getLogger(PageableController.class);

        @Get(produces = APPLICATION_JSON, value = "/test{?pageable}")
        public Page<String> getNames(@Nullable Pageable pageable) {

            LOGGER.info("pageable {}", pageable);
            if( pageable == null){
                return Page.of(Arrays.asList("foo", "bar"), Pageable.UNPAGED, 2);
            }else{
                return Page.of(Arrays.asList("foo", "bar"), pageable, 2);
            }
        }
    }

我希望能够用这样的方式调用它。但目前记录器显示可分页始终为空:

    @MicronautTest
    class PageableControllerTest {

        @Inject
        @Client("/")
        private RxHttpClient client;

        @Test
        void callsWithPageable() {
            String uri = "/test?size=20&number=2";
            String orders = client.toBlocking().retrieve(HttpRequest.GET(uri));

            //TODO, assert orders and pagination
        }

如果我们可以用类似的东西来测试它会更好:

    @Test
    void callsWithPageableParsingJson() {
        String uri = "/test?size=20&number=2";

        //This fails to parse as it can't build pages.
        Page<String> pages = client.toBlocking().retrieve(HttpRequest.GET(uri), pageOf(String.class));

        assertThat(pages.getSize(),   is(2));
        assertThat(pages.getContent(), contains("foo", "bar"));
    }

    // Inspired by Argument.listOf
    private static <T> Argument<Page<T>> pageOf(Class<T> type) {
        return Argument.of((Class<Page<T>>) ((Class) Page.class), type);
    }

Micronaut bug 表明正确的分页方式是使用 Micronaut 数据

"/test{?pageable}" 表示绑定到一个名为 pageable

的单个查询值

"/test{?pageable*}" 表示将所有查询值绑定到一个名为 pageable

的参数

你想要后者

在我的申请中,我也接受 Pageable,我对此没有任何问题。我和你的区别是:

  1. 我的路径只是 @Get("/test") 即没有 {pageable} 部分。
  2. 我没有让我的 Pageable 成为 @Nullable。从我可以从 micronaut 代码中追踪到的,它不会像对待任何其他对象一样对待 Pageable。它有特殊的处理方式(比如测试参数类型是否为 Pageable,如果是,则执行某些操作)。

你能试试这两件事吗?

问题已通过添加以下依赖项解决:

    <dependency>
       <groupId>io.micronaut.data</groupId>
       <artifactId>micronaut-data-runtime</artifactId>
       <version>1.0.0.M1</version>
    </dependency>

我的控制器层可以访问 micronaut-data-model 但这个 jar 包含重要的 class PageableRequestArgumentBinder。只要在 classpath 中,它就会自动作为活页夹注入,无需额外配置。

是的,Free See 是正确的,现在我可以从路径中删除可分页参数,并且方法中的参数不需要是 @Nullable :

    @Controller
    public class PageableController {

        private static final Logger LOGGER = LoggerFactory.getLogger(PageableController.class);

        @Get(produces = APPLICATION_JSON, value = "/test")
        public Page<String> getNames(Pageable pageable) {

            LOGGER.info("pageable {}", pageable);
            return Page.of(Arrays.asList("foo", "bar", "baz"), pageable, 3);
        }

要调用它,我们将使用 standard parameters names defined in DataConfiguration.PageableConfiguration

  • DEFAULT_PAGE_PARAMETER "page"
  • DEFAULT_SIZE_PARAMETER "size"
  • DEFAULT_SORT_PARAMETER "sort"

如果您想使用不同的参数,您可以使用属性进行更改:

micronaut:
  data:
    pageable:
     max-page-size: 500

你可以用

测试它
    @Test
    void callsWithPageable() {
        String uri = "/test?page=1&size=2";

        Page<String> pages = client.toBlocking().retrieve(HttpRequest.GET(uri), pageOf(String.class));

        assertThat(pages.getPageNumber(),   is(1));
        assertThat(pages.getTotalPages(),   is(2));
        assertThat(pages.getSize(),   is(2));
        assertThat(pages.getContent(), contains("foo", "bar", "baz"));
    }

而且,为了使事情变得更好,客户端可以使用 returns 参数>

的 pageOf 方法将结果转换为页面