如何用WebClient非阻塞实现:过滤非Fork仓库并提取Mono<Branch[]>中的Branch[]
WebClient实现GitHub非Fork仓库及分支列表获取方案
针对你遇到的两个问题,直接给出解决方案:
1. 过滤非Fork仓库
不需要先将响应赋值给变量再过滤,直接在getRepos返回的Flux<Repo>上使用filter操作符即可,过滤掉fork为true的仓库:
private Flux<Repo> getRepos(String username) { return webClient .get() .uri("/users/{username}/repos", username) .retrieve() .bodyToFlux(Repo.class) // 过滤非Fork仓库,同时处理fork字段为null的边界情况 .filter(repo -> repo.fork() == null || !repo.fork()); }
这里用URI模板{username}代替字符串拼接,更规范且避免潜在的语法问题。
2. 从Mono<Branch[]>提取数据构建ResponseRepo
getBranches返回的是异步类型Mono<Branch[]>,不能同步提取值。需要通过zip操作将当前仓库的信息与分支数据异步组合,再映射为ResponseRepo:
修改getReposInfo方法如下:
public Flux<ResponseRepo> getReposInfo(String username) { return getRepos(username) .flatMap(repo -> Mono.zip( Mono.just(repo), getBranches(username, repo.name()) ).map(tuple -> new ResponseRepo( tuple.getT1().name(), tuple.getT1().owner().login(), tuple.getT2() ))); }
Mono.zip会等待两个异步操作完成后,将结果封装为元组,再通过map转换为目标对象。
完整修改后的代码
@Service public class RepoServiceImpl implements RepoService { private final WebClient webClient; public RepoServiceImpl(WebClient.Builder builder) { this.webClient = builder.baseUrl("https://api.github.com").build(); } public Flux<ResponseRepo> getReposInfo(String username) { return getRepos(username) .flatMap(repo -> Mono.zip( Mono.just(repo), getBranches(username, repo.name()) ).map(tuple -> new ResponseRepo( tuple.getT1().name(), tuple.getT1().owner().login(), tuple.getT2() ))); } private Flux<Repo> getRepos(String username) { return webClient .get() .uri("/users/{username}/repos", username) .retrieve() .bodyToFlux(Repo.class) .filter(repo -> repo.fork() == null || !repo.fork()); } private Mono<Branch[]> getBranches(String username, String repo) { return webClient .get() .uri("/repos/{username}/{repo}/branches", username, repo) .retrieve() .bodyToMono(Branch[].class); } }
内容的提问来源于stack exchange,提问作者robertos
相关产品推荐
相关产品推荐

