私は私の理解を固めるために、いくつかのREST呼び出しを行うにしようとしています、それの一環としてのJava 8のCompletableFutureを理解しようとしています。:私は、REST呼び出しにするために、このライブラリを使用していhttps://github.com/AsyncHttpClient/async-http-clientを。
、このライブラリはGET呼び出しのレスポンスオブジェクトを返しますのでご注意ください。
以下は、私がしようとしているものです。
- ユーザーのリストを提供します。このURLを呼び出します。https://jsonplaceholder.typicode.com/users
- GSONを使用してユーザーオブジェクトのリストへの対応を変換します。
- リスト内の各ユーザーオブジェクトを反復処理は、ユーザIDを取得し、次のURLからユーザによってなされた記事の一覧を取得:https://jsonplaceholder.typicode.com/posts?userId=1
- GSONを使用してポストオブジェクトへの各ポストの応答を変換します。
ユーザーオブジェクトとユーザーによって行われた投稿のリストを持っているそれぞれのUserPostオブジェクトのコレクションを、ビルドします。
public class UserPosts { private final User user; private final List<Post> posts; public UserPosts(User user, List<Post> posts) { this.user = user; this.posts = posts; } @Override public String toString() { return "user = " + this.user + " \n" + "post = " + posts+ " \n \n"; }
}
次のように私は現在、それが実装されています:
package com.CompletableFuture;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.asynchttpclient.Response;
import com.http.HttpResponse;
import com.http.HttpUtil;
import com.model.Post;
import com.model.User;
import com.model.UserPosts;
/**
* Created by vm on 8/20/18.
*/
class UserPostResponse {
private final User user;
private final Future<Response> postResponse;
UserPostResponse(User user, Future<Response> postResponse) {
this.user = user;
this.postResponse = postResponse;
}
public User getUser() {
return user;
}
public Future<Response> getPostResponse() {
return postResponse;
}
}
public class HttpCompletableFuture extends HttpResponse {
private Function<Future<Response>, List<User>> userResponseToObject = user -> {
try {
return super.convertResponseToUser(Optional.of(user.get().getResponseBody())).get();
} catch (Exception e) {
e.printStackTrace();
return null;
}
};
private Function<Future<Response>, List<Post>> postResponseToObject = post -> {
try {
return super.convertResponseToPost(Optional.of(post.get().getResponseBody())).get();
} catch (Exception e) {
e.printStackTrace();
return null;
}
};
private Function<UserPostResponse, UserPosts> buildUserPosts = (userPostResponse) -> {
try {
return new UserPosts(userPostResponse.getUser(), postResponseToObject.apply(userPostResponse.getPostResponse()));
} catch (Exception e) {
e.printStackTrace();
return null;
}
};
private Function<User, UserPostResponse> getPostResponseForUser = user -> {
Future<Response> resp = super.getPostsForUser(user.getId());
return new UserPostResponse(user, resp);
};
public HttpCompletableFuture() {
super(HttpUtil.getInstance());
}
public List<UserPosts> getUserPosts() {
try {
CompletableFuture<List<UserPosts>> usersFuture = CompletableFuture
.supplyAsync(() -> super.getUsers())
.thenApply(userResponseToObject)
.thenApply((List<User> users)-> users.stream().map(getPostResponseForUser).collect(Collectors.toList()))
.thenApply((List<UserPostResponse> userPostResponses ) -> userPostResponses.stream().map(buildUserPosts).collect(Collectors.toList()));
List<UserPosts> users = usersFuture.get();
System.out.println(users);
return users;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
私はこれをやっている方法が正しい場合は、私はわかりません。具体的には、中userResponseToObject
およびpostResponseToObject
機能、私は呼び出していますget()
ブロックされます将来、上の方法を。
これを実装するための良い方法はありますか?
あなたが使用することを計画している場合CompletableFuture
、あなたは使うべきListenableFuture
非同期HTTPクライアントライブラリから。ListenableFuture
に変換することができますCompletableFuture
。
使用しての利点は、CompletableFuture
あなたが扱っロジック書くことができるということであるResponse
先物やスレッドについて何も知らなくてもオブジェクトを。あなたは、次の4つの方法を書いたとします。解析応答に要求し、2を作るために2:
ListenableFuture<Response> requestUsers() {
}
ListenableFuture<Response> requestPosts(User u) {
}
List<User> parseUsers(Response r) {
}
List<UserPost> parseUserPosts(Response r, User u) {
}
今、私たちは与えられたユーザのための非ブロッキング方法その取り出し記事を書くことができます。
CompletableFuture<List<UserPost>> userPosts(User u) {
return requestPosts(u)
.toCompletableFuture()
.thenApply(r -> parseUserPosts(r, u));
}
そして、すべてのユーザーのすべての記事を読むためにブロックする方法:
List<UserPost> getAllPosts() {
// issue all requests
List<CompletableFuture<List<UserPost>>> postFutures = requestUsers()
.toCompletableFuture()
.thenApply(userRequest -> parseUsers(userRequest)
.stream()
.map(this::userPosts)
.collect(toList())
).join();
// collect the results
return postFutures.stream()
.map(CompletableFuture::join)
.flatMap(List::stream)
.collect(toList());
}