我做了类似的事情......我的目标是创建一个带有这样签名的方法:
Flux getIssues(WebClient webClient);
因为我打电话的网站只提供了分页界面,所以我需要将多个REST调用的结果提供给一个Flux . 以下是我的实施 . 请注意我使用CachedThreadPool .
Flux getIssues(WebClient webClient) {
return Flux.generate(
() -> new IssuesState(webClient),
(state, sink) -> {
BasicIssue ret = state.getNext();
if (ret == null) {
sink.complete();
} else {
sink.next(ret);
}
return state;
}
}
class IssuesState {
private final AtomicBoolean isDone = new AtomicBoolean(false);
private final AtomicInteger threadCount = new AtomicInteger(1);
private final Executor executor = Executors.newCachedThreadPool();
private final LinkedBlockingQueue issueQueue = new LinkedBlockingQueue();
public IssuesState(WebClient webClient) {
executor.execute(() -> getNextBlock(webClient, 0));
}
private void getNextBlock(final WebClient webClient, final int startAt) {
webClient
.get()
.uri(...)
.header("Authorization", "Basic " + Base64Utils.encodeToString(("username:password".getBytes(UTF_8))))
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(PageableIssue.class)
.subscribe(pageableIssue -> {
int maxResults = pageableIssue.getMaxResults();
int total = pageableIssue.getTotal();
if (startAt == 0) {
for (int i = startAt + maxResults; i < total; i += maxResults) {
threadCount.incrementAndGet();
final int x = i;
executor.execute(() -> getNextBlock(webClient, x));
}
}
synchronized (issueQueue) {
for (BasicIssue issue : pageableIssue.getIssues()) {
issueQueue.add(issue);
}
if (threadCount.decrementAndGet() == 0) {
isDone.set(true);
}
}
});
}
public BasicIssue getNext() {
synchronized (issueQueue) {
if (isDone.get() && issueQueue.isEmpty()) {
return null;
}
}
try {
return issueQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
使用上面的方法..
getIssues(webClient)
.subscribe(basicIssue -> System.out.println(basicIssue.getName());