AWS выпустила AWS SDK для Java версии 2 , теперь SDK поддерживает неблокирующий ввод-вывод для вызовов API различных сервисов AWS. В этой статье я расскажу об использовании API-интерфейса DynamoDB в AWS SDK 2.x и использовании стека Spring Webflux для демонстрации реактивной конечной точки — таким образом, приложение является реактивным сквозным и предположительно должно использовать ресурсы очень эффективно (у меня есть планы сделайте несколько тестов на этой установке в качестве продолжения).
Детали заявки
Может быть проще просто посмотреть на код и следовать ему там — он доступен в моем репозитории GitHub .
Приложение простое — для выполнения операции CRUD на объекте Hotel, представленном с использованием следующего кода Kotlin:
1
2
3
4
5
6
7
|
data class Hotel( val id: String = UUID.randomUUID().toString(), val name: String? = null , val address: String? = null , val state: String? = null , val zip: String? = null ) |
Я хочу выставить конечные точки для сохранения и извлечения объекта отеля, а также для получения списка отелей по штатам.
Подробная информация о AWS SDK 2
Имена пакетов API-интерфейса AWS SDK 2 теперь начинаются с префикса «software.amazon.awssdk», клиент для взаимодействия с DynamoDB создается с использованием следующего кода:
1
2
3
4
5
6
7
8
|
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider import software.amazon.awssdk.regions.Region import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient val client: DynamoDbAsyncClient = DynamoDbAsyncClient.builder() .region(Region.of(dynamoProperties.region)) .credentialsProvider(DefaultCredentialsProvider.builder().build()) .build() |
После создания экземпляра DynamoDbAsyncClient любая операция, использующая этот клиент, возвращает тип Java 8 CompletableFuture . Например, в спасении гостиничного предприятия:
1
2
3
4
5
6
7
|
val putItemRequest = PutItemRequest.builder() .tableName( "hotels" ) .item(HotelMapper.toMap(hotel)) .build() val result: CompletableFuture<PutItemResponse> = dynamoClient.putItem(putItemRequest) |
и при получении записи по id:
1
2
3
4
5
6
|
val getItemRequest: GetItemRequest = GetItemRequest.builder() .key(mapOf(Constants.ID to AttributeValue.builder().s(id).build())) .tableName(Constants.TABLE_NAME) .build() val response: CompletableFuture<GetItemResponse> = dynamoClient.getItem(getItemRequest) |
CompletableFuture предоставляет полный набор функций для преобразования результатов при их наличии.
Интеграция с Spring Webflux
Spring Webflux — это реактивный веб-фреймворк. Поддержка неблокирующего ввода-вывода в AWS SDK 2 теперь позволяет писать сквозные динамические и неблокирующие приложения с DynamoDB. Spring Webflux использует реакторное ядро для обеспечения поддержки реактивных потоков, а хитрость интеграции с AWS SDK 2 заключается в преобразовании Java 8 CompletableFuture в тип реакторного ядра следующим образом при получении элемента из DynamoDB по id:
1
2
3
4
5
6
7
8
9
|
val getItemRequest: GetItemRequest = GetItemRequest.builder() .key(mapOf(Constants.ID to AttributeValue.builder().s(id).build())) .tableName(Constants.TABLE_NAME) .build() return Mono.fromCompletionStage(dynamoClient.getItem(getItemRequest)) .map { resp -> HotelMapper.fromMap(id, resp.item()) } |
Spring Webflux ожидает, что типы возврата различных сигнатур метода конечной точки сети будут иметь реактивные типы, поэтому типичной конечной точкой для получения списка отелей является следующее:
1
2
3
4
|
@RequestMapping (value = [ "/hotels" ], method = [RequestMethod.GET]) fun getHotelsByState( @RequestParam ( "state" ) state: String): Flux<Hotel> { return hotelRepo.findHotelsByState(state) } |
Spring Webflux также поддерживает функциональный способ описания API приложения, поэтому эквивалентный API для извлечения отеля по его идентификатору, но в виде функционального DSL, выглядит следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
@Configuration class HotelAdditionalRoutes { @Bean fun routes(hotelRepo: HotelRepo) = router { GET( "/hotels/{id}" ) { req -> val id = req.pathVariable( "id" ) val response: Mono<ServerResponse> = hotelRepo.getHotel(id) .flatMap { hotel -> ServerResponse.ok().body(BodyInserters.fromObject(hotel)) } response.switchIfEmpty(ServerResponse.notFound().build()) } } } |
Вывод
AWS SDK 2 упрощает написание сквозных реактивных и неблокирующих приложений. Я использовал Spring Webflux и AWS SDK 2 динамо-клиент, чтобы написать такое приложение здесь. Весь рабочий образец доступен в моем репозитории GitHub — https://github.com/bijukunjummen/boot-with-dynamodb, и в нем содержатся инструкции о том, как запустить локальную версию DynamoDB и использовать ее для тестирования приложения.
Смотреть оригинальную статью здесь: Reactive Spring Webflux с AWS DynamoDB
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |