使用 Java 在 Play 框架中链式承诺
Chain Promises in Play Framework Using Java
我有一个控制器操作,我需要调用第 3 方 Web 服务。
我的问题是我没有调用一项网络服务。我需要链接 4 到 5 个 Web 服务。我调用的每个 Web 服务 return 都是我需要处理的 JSON 对象,根据某些逻辑,我决定调用另一个 Web 服务(来自 4 个 Web 服务)或 return 响应给来电者。这是我正在尝试做的事情:
public static Promise<Result> accounts(){
return WS.url("url1").get().map(response1 -> {
JsonNode mynode = response1.asJson();
if (mynode.get("status").asInt()==200){
Promise<JsonNode> jsonPromise = WS.url("url2").get().map(response2->{
return response2.asJson();
});
}
return ok(mynode);
});
}
现在,根据文档,我认为我需要的是链接承诺,其中每个 Web 服务调用都是一个承诺。但我不确定该怎么做?
谢谢
他们称之为 Reactive Composition 并且它是这样完成的 ->
public static Promise<Result> reactiveCombo() {
Promise<WSResponse> promise1 = WS.url("url1").get();
Promise<WSResponse> promise2 = WS.url("url2").get();
Promise<WSResponse> promise3 = WS.url("url3").get();
return promise1.flatMap(response1 -> {
final JsonNode json1 = response1.asJson();
if (!json1.has("someField")) {
return Promise.promise(() -> badRequest());
}
return promise2.flatMap(response2 -> {
final JsonNode json2 = response2.asJson();
if (json1.get("someField").asText().equals(json2.get("someField").asText())) {
return Promise.promise(() -> badRequest());
}
return promise3.map(response3 -> {
final JsonNode json3 = response3.asJson();
if (json3.get("boolField").asBoolean()) {
return badRequest();
}
return ok();
});
});
});
}
对于大量调用,您可以使用 Promise.sequence()
并获得 'creative':
private static Promise<JsonNode> getPromise(String url, Predicate<JsonNode> predicate) {
return WS.url(url).get().map(response -> {
JsonNode json = response.asJson();
if (predicate.negate().test(json)) {
throw new Exception("BUMMER!");
}
return json;
});
}
public static Promise<Result> reactiveCombo(List<String> urls) {
List<Promise<JsonNode>> promises = new ArrayList<Promise<JsonNode>>(urls.size());
Predicate<String> predURL = p -> p.contains("goodApi");
Predicate<JsonNode> pred1 = p -> p.has("boolField") && p.get("boolField").asBoolean();
Predicate<JsonNode> pred2 = p -> p.has("someField");
urls.forEach(url -> {
Promise<JsonNode> promise = predURL.test(url) ? getPromise(url, pred1) : getPromise(url, pred2);
promises.add(promise);
});
return Promise.sequence(promises).map(results -> ok()).recover(t -> badRequest());
}
其他详细信息 + 纪录片:
Go Reactive with Java 8 & Play Framework(老了但仍然有教育意义)
对于任意数量的 Promise,您可以使用递归来展平这个结构。
首先创建一个class:
public static class ChainedWebService {
public final Optional<ChainedWebService> next;
public final WSRequestHolder wsResponsePromise;
private final F.Predicate<JsonNode> predicate;
public ChainedWebService(String url, Optional<ChainedWebService> next, F.Predicate<JsonNode> predicate) {
this.next = next;
this.wsResponsePromise = WS.url(url);
this.predicate = predicate;
}
public F.Promise<Result> processChain() {
return wsResponsePromise.get().flatMap(new F.Function<WSResponse, F.Promise<Result>>() {
@Override
public F.Promise<Result> apply(WSResponse wsResponse) throws Throwable {
if (!predicate.test(wsResponse.asJson())) {
return F.Promise.pure(badRequest());
}
if (!next.isPresent()) {
return F.Promise.pure(ok());
}
return next.get().processChain();
}
});
}
}
然后使用它:
public static F.Promise<Result> reactiveCombo() {
ChainedWebService chainedWebService3 = new ChainedWebService(
"url3",
Optional.<ChainedWebService>empty(),
jsonNode -> jsonNode.get("boolField").asBoolean()
);
ChainedWebService chainedWebService2 = new ChainedWebService(
"url2",
Optional.of(chainedWebService3),
jsonNode -> jsonNode.get("someField").asText().equals(jsonNode.get("someField").asText()));
ChainedWebService chainedWebService1 = new ChainedWebService(
"url1",
Optional.of(chainedWebService2),
jsonNode -> jsonNode.has("someField")
);
return chainedWebService1.processChain();
}
您可以实现一些基本的构建器,使构建过程更加合理。
希望对您有所帮助!
我有一个控制器操作,我需要调用第 3 方 Web 服务。
我的问题是我没有调用一项网络服务。我需要链接 4 到 5 个 Web 服务。我调用的每个 Web 服务 return 都是我需要处理的 JSON 对象,根据某些逻辑,我决定调用另一个 Web 服务(来自 4 个 Web 服务)或 return 响应给来电者。这是我正在尝试做的事情:
public static Promise<Result> accounts(){
return WS.url("url1").get().map(response1 -> {
JsonNode mynode = response1.asJson();
if (mynode.get("status").asInt()==200){
Promise<JsonNode> jsonPromise = WS.url("url2").get().map(response2->{
return response2.asJson();
});
}
return ok(mynode);
});
}
现在,根据文档,我认为我需要的是链接承诺,其中每个 Web 服务调用都是一个承诺。但我不确定该怎么做?
谢谢
他们称之为 Reactive Composition 并且它是这样完成的 ->
public static Promise<Result> reactiveCombo() {
Promise<WSResponse> promise1 = WS.url("url1").get();
Promise<WSResponse> promise2 = WS.url("url2").get();
Promise<WSResponse> promise3 = WS.url("url3").get();
return promise1.flatMap(response1 -> {
final JsonNode json1 = response1.asJson();
if (!json1.has("someField")) {
return Promise.promise(() -> badRequest());
}
return promise2.flatMap(response2 -> {
final JsonNode json2 = response2.asJson();
if (json1.get("someField").asText().equals(json2.get("someField").asText())) {
return Promise.promise(() -> badRequest());
}
return promise3.map(response3 -> {
final JsonNode json3 = response3.asJson();
if (json3.get("boolField").asBoolean()) {
return badRequest();
}
return ok();
});
});
});
}
对于大量调用,您可以使用 Promise.sequence()
并获得 'creative':
private static Promise<JsonNode> getPromise(String url, Predicate<JsonNode> predicate) {
return WS.url(url).get().map(response -> {
JsonNode json = response.asJson();
if (predicate.negate().test(json)) {
throw new Exception("BUMMER!");
}
return json;
});
}
public static Promise<Result> reactiveCombo(List<String> urls) {
List<Promise<JsonNode>> promises = new ArrayList<Promise<JsonNode>>(urls.size());
Predicate<String> predURL = p -> p.contains("goodApi");
Predicate<JsonNode> pred1 = p -> p.has("boolField") && p.get("boolField").asBoolean();
Predicate<JsonNode> pred2 = p -> p.has("someField");
urls.forEach(url -> {
Promise<JsonNode> promise = predURL.test(url) ? getPromise(url, pred1) : getPromise(url, pred2);
promises.add(promise);
});
return Promise.sequence(promises).map(results -> ok()).recover(t -> badRequest());
}
其他详细信息 + 纪录片:
Go Reactive with Java 8 & Play Framework(老了但仍然有教育意义)
对于任意数量的 Promise,您可以使用递归来展平这个结构。 首先创建一个class:
public static class ChainedWebService {
public final Optional<ChainedWebService> next;
public final WSRequestHolder wsResponsePromise;
private final F.Predicate<JsonNode> predicate;
public ChainedWebService(String url, Optional<ChainedWebService> next, F.Predicate<JsonNode> predicate) {
this.next = next;
this.wsResponsePromise = WS.url(url);
this.predicate = predicate;
}
public F.Promise<Result> processChain() {
return wsResponsePromise.get().flatMap(new F.Function<WSResponse, F.Promise<Result>>() {
@Override
public F.Promise<Result> apply(WSResponse wsResponse) throws Throwable {
if (!predicate.test(wsResponse.asJson())) {
return F.Promise.pure(badRequest());
}
if (!next.isPresent()) {
return F.Promise.pure(ok());
}
return next.get().processChain();
}
});
}
}
然后使用它:
public static F.Promise<Result> reactiveCombo() {
ChainedWebService chainedWebService3 = new ChainedWebService(
"url3",
Optional.<ChainedWebService>empty(),
jsonNode -> jsonNode.get("boolField").asBoolean()
);
ChainedWebService chainedWebService2 = new ChainedWebService(
"url2",
Optional.of(chainedWebService3),
jsonNode -> jsonNode.get("someField").asText().equals(jsonNode.get("someField").asText()));
ChainedWebService chainedWebService1 = new ChainedWebService(
"url1",
Optional.of(chainedWebService2),
jsonNode -> jsonNode.has("someField")
);
return chainedWebService1.processChain();
}
您可以实现一些基本的构建器,使构建过程更加合理。
希望对您有所帮助!