最简WebClient 同步、异步调用示例

时间:2025-04-04 22:18:39
//goto <?xml version="1.0" encoding="UTF-8"?> <project xmlns="/POM/4.0.0" xmlns:xsi="http:///2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0."> <modelVersion>4.0.0</modelVersion> <groupId>com.fly</groupId> <artifactId>web-client</artifactId> <version>0.0.1</version> <name>web-client</name> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <skipTests>true</skipTests> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webflux</artifactId> <version>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty</artifactId> <version>0.9.4.RELEASE</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.12.1</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.10</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.0</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <minimizeJar>false</minimizeJar> <filters> <filter> <artifact>*:*</artifact> </filter> </filters> <transformers> <!--MANIFEST文件中写入Main-Class是可执行包的必要条件。ManifestResourceTransformer可以轻松实现。 --> <transformer implementation=""> <mainClass>com.fly.http.RunWebClient</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> //goto src\main\java\com\fly\http\ package com.fly.http; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.client.WebClient; import lombok.extern.slf4j.Slf4j; /** * WebClient是RestTemplete的替代品,有更好的响应式能力,支持异步调用<br> * * /zzhongcy/article/details/105412842 * */ @Slf4j public class FluxWebClient { private List<String> urls = new ArrayList<>(); // 缓冲区默认256k,设为-1以解决报错Exceeded limit on max bytes to buffer : 262144 private WebClient webClient = WebClient.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build(); public void visitAll() { // block转换为同步调用 if (urls.isEmpty()) { String resp = webClient.get().uri("/upload/").acceptCharset(StandardCharsets.UTF_8).accept(MediaType.TEXT_HTML).retrieve().bodyToMono(String.class).block(); urls = Arrays.asList(StringUtils.split(resp, "\r\n")); log.info("★★★★★★★★ urls:"); urls.stream().forEach(log::info); } // 异步访问 AtomicInteger count = new AtomicInteger(0); urls.stream() .filter(url -> RandomUtils.nextBoolean()) .forEach(url -> webClient.get() .uri(url) .acceptCharset(StandardCharsets.UTF_8) .accept(MediaType.TEXT_HTML) .retrieve() .bodyToMono(String.class) .subscribe(r -> log.info("process complted: {}. {}", count.incrementAndGet(), url), e -> log.error(e.getMessage()))); log.info("total:{} ==> ############## 异步请求已提交 ##############", urls.size()); } } //goto src\main\java\com\fly\http\ package com.fly.http; import java.util.Timer; import java.util.TimerTask; import lombok.extern.slf4j.Slf4j; @Slf4j public class RunMain { /** * 程序运行入口 * * @param args */ public static void main(String[] args) { // Timer线程安全, 但单线程执行, 抛出异常时, task会终止 FluxWebClient webClient = new FluxWebClient(); new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { webClient.visitAll(); } }, 0L, 30 * 1000L); log.info("======== Timer started!"); } } //goto src\main\resources\ <?xml version="1.0" encoding="UTF-8"?> <configuration status="off" monitorInterval="0"> <appenders> <console name="Console" target="system_out"> <patternLayout pattern="%d{yyyy-MM-dd HH:mm:} [%t] %-5level %logger{36} - %msg%n" /> </console> </appenders> <loggers> <root level="INFO"> <appender-ref ref="Console" /> </root> </loggers> </configuration>