尝试在Java播放框架2.8中创建API。 我不知道我编写的代码出了什么问题,但这没用。
我在localhost:9000收到此响应
{"result":null,"stack":null,"done":false,"cancelled":false,"completedExceptionally":false,"numberOfDependents":0}
我认为我在异步调用方面缺少一些东西,因为当我尝试单独运行代码时,它可以工作(使用邮递员或其他游乐场类)。
我正在上传代码,很高兴知道代码有什么问题。 预先感谢!
package utils;
import com.fasterxml.jackson.databind.JsonNode;
import models.Commit;
import play.libs.ws.WSResponse;
import javax.inject.Inject;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
public class CommitsService {
private BBService bbService;
@Inject
public CommitsService(BBService bbService) {
this.bbService = bbService;
}
public CompletionStage<CompletableFuture<List<Commit>>> retrieveCommitsForUser(String username) {
CompletionStage<List<String>> reposPromise = getRepos();
return reposPromise
.thenApplyAsync(repos -> sequence(repos.stream()
.map(repo -> getRepoCommits(repo))
.collect(Collectors.toList()))
.thenApplyAsync(responses -> {
List<Commit> allCommits = responses.stream()
.map(wsResponse -> extractCommits(wsResponse))
.flatMap(List::stream).filter(commit -> isByUser(commit, username) && isLastDay(commit))
.collect(Collectors.toList());
return allCommits;
}));
}
private CompletionStage<List<String>> getRepos() {
return bbService.getRepos()
.thenApplyAsync(response -> extractRepos(response));
}
private List<String> extractRepos(WSResponse wsResponse) {
Vector<String> repos = new Vector<>();
JsonNode reposAsJson = wsResponse.asJson().findValue("values");
for (JsonNode repo : reposAsJson) {
String repoName = repo.path("name").asText();
repos.add(repoName);
}
return repos;
}
private CompletableFuture<WSResponse> getRepoCommits(String repo) {
return bbService.getRepoCommits(repo).toCompletableFuture();
}
private boolean isByUser(Commit commit, String username) {
return commit.getAuthor().equals(username);
}
private boolean isLastDay(Commit commit) {
String sDate = commit.getDate().substring(0, commit.getDate().indexOf('T'));
String sTime = commit.getDate().substring(commit.getDate().indexOf('T'), commit.getDate().length() - 1);
return true;
}
private List<Commit> extractCommits(WSResponse wsResponse) {
Vector<Commit> allCommits = new Vector<>();
JsonNode commits = wsResponse.asJson().findValue("values");
for (JsonNode commit : commits) {
String HASH = commit.path("hash").asText();
String date = commit.path("date").asText();
String repo = commit.path("repository").path("name").asText();
String message = commit.path("message").asText();
String author = commit.path("author").path("user").path("display_name").asText();
Commit currCommit = new Commit(HASH, date, repo, message, author);
allCommits.add(currCommit);
}
return allCommits;
}
public <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futuresList) {
return CompletableFuture
.allOf(futuresList.toArray(new CompletableFuture[0])) // (1)
.thenApply(v ->
futuresList.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
}
}
package controllers;
import play.libs.Json;
import play.mvc.*;
import utils.CommitsService;
import javax.inject.Inject;
import java.util.concurrent.CompletionStage;
/**
* Commits controller is handling in and out http traffic regarding bitbucket commits.
* Supporting get but can be expanded to other crud operations.
*/
public class CommitsController extends Controller {
private final CommitsService commitsService;
@Inject
public CommitsController(CommitsService commitsService) {
this.commitsService = commitsService;
}
public CompletionStage<Result> showCommits(String username) {
return commitsService.retrieveCommitsForUser(username)
.thenApplyAsync(res -> ok(Json.toJson(res)));
}
}
package utils;
import com.fasterxml.jackson.databind.JsonNode;
import play.libs.ws.*;
import play.mvc.Result;
import javax.inject.Inject;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
public class BBService {
private final String BB_BASE_URL = "https://api.bitbucket.org/2.0/";
private final String URL = BB_BASE_URL + "repositories/******/";
private final String COMMITS = "commits";
private final String bbUsername = "*******";
private final String bbPassword = "*******";
private final WSClient ws;
@Inject
public BBService(WSClient ws) {
this.ws = ws;
}
public CompletionStage<WSResponse> getAsync(String url) {
WSRequest req = ws.url(url).setAuth(bbUsername, bbPassword);
return req.get();
}
public List<String> extractNames(WSResponse wsResponse) {
Vector<String> usersNames = new Vector<>();
JsonNode users = wsResponse.asJson().findValue("values");
for (JsonNode user : users) {
String userName = user.findValue("display_name").asText();
usersNames.add(userName);
}
return usersNames;
}
public CompletionStage<WSResponse> getRepos() {
return getAsync(URL);
}
public CompletionStage<WSResponse> getRepoCommits(String repoName) {
return getAsync(URL + repoName + "/" + COMMITS);
}
public Result withFullAccess(Result noAccessibleRes) {
return noAccessibleRes.withHeader("Access-Control-Allow-Origin", "*");
}
public <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futuresList) {
return CompletableFuture
.allOf(futuresList.toArray(new CompletableFuture[0])) // (1)
.thenApply(v ->
futuresList.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
}
}
答案 0 :(得分:1)
考虑到您得到的响应,问题在于您在CompletableFuture<List<Commit>>
中以List<Commit>
类型而不是CommitsController
作为响应对象:
retrieveCommitsForUser(username)
.thenApplyAsync(res -> ok(Json.toJson(res)))
在其中输入类型res
的{{1}}-这就是为什么您会看到此类中所有字段的原因。
您要做的是返回方法CompletableFuture<List<Commit>>
而不是CommitsService.retrieveCommitsForUser
来返回CompletionStage<List<Commit>>
。
CompletionStage<CompletableFuture<List<Commit>>>
可以帮助您-它可以将当前CompletionStage.thenComposeAsync
的执行与下一次CompletionStage
的执行联系起来。
因此最终的溶液可能看起来像:
CompletionStage
希望这会有所帮助!