最初の部分では、反応性とは何か、基本的なレベルでどのように反応するかを学びました。 新しいSpringフレームワークを使用してリアクティブプログラミングを引き続き検討する場合は、ようこそ!
ここで、前の記事で得た知識をどうするかを分析し、非同期モードで動作する小さなWebサービスを構築します。
これには次のものが必要です。
- MongoDBデータベース 。 実際、すべてのDBMSが非同期操作をサポートしているわけではありません。 この意味でのMongoDBは快適に異なり、必要な機能を完全にサポートしています。
- データベースとの非同期操作用のドライバー 。 通常のドライバーは、その方法を知りません。
- スプリングブート2 。 Spring Bootは現在開発中ですが、 12月18日にリリースされる予定です。 これにより作業が大幅に促進され、多くの時間を節約できます。
- Gradle:ビルドシステムとして使用されます。
- Java 8 。 はい、これは現時点では最新バージョンではありませんが、私たちの目的には非常に適しています。
- ロンボク 。 コードの短縮に役立ちます。
すべての設定と最終プロジェクトはgithubで表示できます。
さあ始めましょう
すべての依存関係をまだ接続していない場合は、すぐに接続できます。 gradleでは、次のようになります。
compile('org.springframework.boot:spring-boot-starter-data-mongodb-reactive') compile('org.springframework.boot:spring-boot-starter-webflux') compileOnly('org.projectlombok:lombok') testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('io.projectreactor:reactor-test')
だから、私たちはすべて設定されています。 まず、アプリケーションのユーザーを作成します。
@Data @AllArgsConstructor @NoArgsConstructor @Document public class User { @Id private String id; private String firstName; private String lastName; }
コンパイルを成功させてIntelliJ Ideaで作業するには、アノテーション処理を有効にするボックスをオンにするか、すべてのセッター、ゲッター、コンストラクターを自分で記述する必要があります。
次に、ユーザーでリポジトリを作成します。
import org.faoxis.habrreactivemongo.domain.User; import org.springframework.data.mongodb.repository.ReactiveMongoRepository; public interface UserRepository extends ReactiveMongoRepository<User, String> { }
ここで、リアクティブモードで動作するための特別なインターフェイスを継承していることに注意してください。 ReactiveMongoRepositoryインターフェースを見ると、すでに知っているMonoクラスとFluxクラスでラップされたオブジェクトを返していることがわかります。 これは、データベースに訴えても、すぐに結果が得られないことを意味します。 代わりに、準備ができたらデータを取得できるデータのストリームを取得します。
多層アーキテクチャは、現在、マイクロサービスアーキテクチャを使用する際の最も一般的なソリューションです。 とても便利です。 サービスレイヤーを作成しましょう。 これを行うには、適切なインターフェイスを作成します。
public interface UserService { Flux<User> get(); Mono<User> save(User user); }
私たちのサービスは非常にシンプルなので、すぐにいくつかの便利なメソッドを作成します。 そして、それらを実現します。
@Service @AllArgsConstructor public class UserServiceImpl implements UserService { private UserRepository userRepository; @Override public Flux<User> get() { return userRepository.findAll(); } @Override public Mono<User> save(User user) { return userRepository.save(user); } }
ここで、UserRepository依存関係の実装は、AllArgsConstructorアノテーションを使用するコンストラクターを通じて行われることに注意してください。 念のため、Spring 4の一部のバージョンでは、 Autowireアノテーションなしでコンストラクターを介して依存関係を自動的に実装できることを思い出させてください 。
最後に、コントローラーを作成します。
import lombok.AllArgsConstructor; import org.faoxis.habrreactivemongo.domain.User; import org.faoxis.habrreactivemongo.service.UserService; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @RestController @RequestMapping("/users") @AllArgsConstructor public class UserController { private UserService userService; @PostMapping public Mono<User> post(@RequestBody User user) { return userService.save(user); } @GetMapping public Flux<User> get() { return userService.get(); } }
アプリケーションを起動します。 すべてが機能するはずです。 ここで、 localhostに POST要求を行います:8080 /次の内容のユーザー:
{ "firstName": "Peter", "lastName": "Griffin" }
応答として、同じオブジェクトを取得しますが、それにIDが割り当てられます。
{ "id": "5a0bf0fdc48fd53478638c9e", "firstName": "Peter", "lastName": "Griffin" }
いいね! さらに数人のユーザーを保存し、データベースにすでにあるものを確認してみましょう。 localhostへのGETリクエストの結果は8080 / usersです。
[ { "id": "5a0bf0fdc48fd53478638c9e", "firstName": "Peter", "lastName": "Griffin" }, { "id": "5a0bf192c48fd53478638c9f", "firstName": "Lois", "lastName": "Griffin" }, { "id": "5a0bf19ac48fd53478638ca0", "firstName": "Mag", "lastName": "Griffin" } ]
いいね! 非同期モードで動作するサービス全体があります! ただし、もう1つ注意すべき点があります。 非同期リポジトリを操作すると、そこからデータを受信するサービスのタイプが大きく変わる可能性があります。
これを実証するには、コントローラーに別のメソッドURLハンドラーを作成します。
@GetMapping("{lastName}") public Flux<User> getByLastName(@PathVariable(name = "lastName") String lastName) { return userService.getByLastName(lastName); }
ここではすべてが簡単です。 ユーザーの姓を取得し、その姓を持つすべての人を表示します。
もちろん、このロジックはデータベースに割り当てることができますが、ここでは、サービスでどのように見えるかに注意を払いたいと思います。
@Override public Flux<User> getByLastName(final String lastName) { return userRepository .findAll() .filter(user -> user.getLastName().equals(lastName)); }
データとデータストリームの操作には違いがあることに注意してください。 通常、データに対していくつかのアクションを直接実行します。 ここで状況は異なります。 データストリームで何をすべきかを言います。
localhost URL:8080 / users / GriffinでGETリクエストを作成してみましょう。 私はこの結果があります:
[ { "id": "5a0bf0fdc48fd53478638c9e", "firstName": "Peter", "lastName": "Griffin" }, { "id": "5a0bf192c48fd53478638c9f", "firstName": "Lois", "lastName": "Griffin" }, { "id": "5a0bf19ac48fd53478638ca0", "firstName": "Mag", "lastName": "Griffin" } ]
この記事では、新しいWebFluxフレームワークとNettyサーバーを使用して非同期サービスを構築する方法を検討しました(デフォルトですぐに使用できます)。 また、 Spring Boot 2を使用してこれを実現するのがどれほど簡単かを確認しました。 プロジェクトにマイクロサービスアーキテクチャがある場合、 Spring Boot 2のリリースでアプリケーションをWebFluxに簡単に転送できる可能性が高いでしょう(もちろん、これが必要な場合)。
PS続けるべきいくつかのアイデアがあります。 素材に興味があり、私のプレゼンテーションに反対でない場合は、次の部分で、たとえば、アプリケーション間の非同期相互作用を検討できます。 ご清聴ありがとうございました!