Поделиться через


Разбиение на страницы и итерация в пакете SDK Azure для Java

В этой статье представлен обзор использования пакета SDK Azure для Java, функций пагинации и итерации для эффективной и продуктивной работы с большими наборами данных.

Многие операции, предоставляемые клиентскими библиотеками в пакете SDK для Java Azure, возвращают несколько результатов. Пакет SDK для Java для Azure определяет в этих случаях набор допустимых типов возвращаемых данных, чтобы обеспечить максимальный опыт разработчика через согласованность. Возвращаемые типы используются PagedIterable для синхронных API и PagedFlux для асинхронных API. API-интерфейсы немного отличаются в зависимости от их различных вариантов использования, но концептуально они имеют одинаковые требования:

  • Это делает возможным легко выполнять итерацию по каждому элементу коллекции по отдельности, игнорируя необходимость ручного разбиения коллекции на страницы или отслеживания маркеров продолжения. Как PagedIterable, так и PagedFlux упрощают выполнение этой задачи, осуществляя итерацию по ответу с разбивкой на страницы, десериализованного в заданный тип T. PagedIterable реализует интерфейс Iterable и предлагает API для получения Stream, в то время как PagedFlux предоставляет Flux. Во всех случаях разбиение на страницы осуществляется прозрачно, и итерация продолжается до тех пор, пока остаются результаты для обработки.

  • Сделайте возможным явную итерацию по страницам. Это позволяет более четко понять, когда выполняются запросы, и дает возможность получать информацию об ответах для каждой страницы. У PagedIterable и PagedFlux есть методы, которые возвращают соответствующие типы для итерации по страницам, а не по отдельным элементам.

Эта статья разделена между синхронными и асинхронными API-интерфейсами Azure SDK для Java. При работе с синхронными клиентами вы увидите API синхронной итерации, а также api асинхронной итерации при работе с асинхронными клиентами.

Синхронное разбиение на страницы и итерация

В этом разделе рассматриваются синхронные API.

Итерировать по отдельным элементам

Как отмечалось, наиболее распространенным вариантом использования является итерация по каждому элементу индивидуально, а не по страницам. В следующих примерах кода показано, как PagedIterable API позволяет использовать стиль итерации, который вы предпочитаете реализовать эту функциональность.

Цикл для каждого элемента

Так как PagedIterable реализуется Iterable, можно выполнить итерацию элементов, как показано в следующем примере:

PagedIterable<Secret> secrets = client.listSecrets();
for (Secret secret : secrets) {
   System.out.println("Secret is: " + secret);
}

Использовать Stream

Поскольку в PagedIterable определён метод stream(), его можно вызвать для использования стандартного Java Stream API, как показано в следующем примере:

client.listSecrets()
      .stream()
      .forEach(secret -> System.out.println("Secret is: " + secret));

Использование итератора

Так как PagedIterable реализует Iterable, он также включает метод iterator(), позволяющий стиль программирования итератора Java, как показано в следующем примере:

Iterator<Secret> secrets = client.listSecrets().iterator();
while (it.hasNext()) {
   System.out.println("Secret is: " + it.next());
}

Произведите перебор страниц

При работе с отдельными страницами можно выполнять итерацию на каждую страницу, например, если требуется информация о ответе HTTP или когда маркеры продолжения важны для хранения журнала итерации. Независимо от того, выполняется ли итерация по страницам или по каждому элементу, нет разницы в производительности или количестве вызовов, сделанных в службу. Базовая реализация загружает следующую страницу по запросу, и если вы откажетесь от подписки из PagedFlux в любой момент, больше нет вызовов к службе.

Цикл для каждого элемента

При выполнении listSecrets() вы получите PagedIterable, который обладает API iterableByPage(). Этот API производит Iterable<PagedResponse<Secret>> вместо Iterable<Secret>. Данный PagedResponse предоставляет метаданные ответа и доступ к токену продолжения, как показано в следующем примере:

Iterable<PagedResponse<Secret>> secretPages = client.listSecrets().iterableByPage();
for (PagedResponse<Secret> page : secretPages) {
   System.out.println("Response code: " + page.getStatusCode());
   System.out.println("Continuation Token: " + page.getContinuationToken());
   page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
}

Существует также iterableByPage перегрузка, которая принимает маркер продолжения. Вы можете вызвать эту перегрузку, если вы хотите вернуться к той же точке итерации позже.

Использовать Stream

В следующем примере показано, как метод streamByPage() выполняет ту же операцию, что и показано выше. Этот API также имеет перегрузку маркера продолжения для возврата к той же точке итерации в дальнейшем.

client.listSecrets()
      .streamByPage()
      .forEach(page -> {
          System.out.println("Response code: " + page.getStatusCode());
          System.out.println("Continuation Token: " + page.getContinuationToken());
          page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
      });

Асинхронное наблюдение за страницами и отдельными элементами

В этом разделе рассматриваются асинхронные API. В асинхронных API сетевые вызовы выполняются в другом потоке, отличном от основного потока, вызывающего subscribe(). Это означает, что основной поток может завершиться до того, как результат будет доступен. Ваша ответственность - убедиться, что приложение не завершает работу до завершения асинхронной операции.

Наблюдение за отдельными элементами

В следующем примере показано, как PagedFlux API позволяет асинхронно наблюдать за отдельными элементами. Существуют различные способы подписки на тип Flux. Дополнительные сведения см. в руководстве по созданию Flux или Mono и подписке на него в руководстве по реактору 3. В этом примере представлен один вариант, в котором есть три лямбда-выражения, по одному для потребителя, потребителя ошибок и полного потребителя. Наличие всех трех компонентов является хорошей практикой, но в некоторых случаях достаточно иметь только потребителя и, возможно, обработчик ошибок.

asyncClient.listSecrets()
   .subscribe(secret -> System.out.println("Secret value: " + secret),
       ex -> System.out.println("Error listing secrets: " + ex.getMessage()),
       () -> System.out.println("Successfully listed all secrets"));

Наблюдайте за страницами

В следующем примере показано, как PagedFlux API позволяет асинхронно наблюдать каждую страницу, снова используя byPage() API и определяя потребителя данных, потребителя ошибок и потребителя завершения.

asyncClient.listSecrets().byPage()
  .subscribe(page -> {
          System.out.println("Response code: " + page.getStatusCode());
          System.out.println("Continuation Token: " + page.getContinuationToken());
          page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
      },
      ex -> System.out.println("Error listing pages with secret: " + ex.getMessage()),
      () -> System.out.println("Successfully listed all pages with secret"));

Дальнейшие шаги

Теперь, когда вы знакомы с разбивкой на страницы и итерацией в пакете SDK Azure для Java, ознакомьтесь с длительными операциями в пакете SDK Azure для Java. Длительные операции — это операции, которые выполняются в течение длительного времени, чем большинство обычных HTTP-запросов, как правило, потому что они требуют некоторых усилий на стороне сервера.