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

一,序言

WebClientspring WebFlux模块提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具,从Spring5.0开始WebClient作为RestTemplete的替代品,有更好的响应式能力,支持异步调用,可以在Spring项目中实现网络请求。

二,简单示例

1. 引入依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>***.fly</groupId>
	<artifactId>web-client</artifactId>
	<version>0.0.1</version>
	<name>base</name>
	<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.***ty</groupId>
			<artifactId>reactor-***ty</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.***mons</groupId>
			<artifactId>***mons-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-***piler-plugin</artifactId>
				<version>3.10.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

2. 日志配置

log4j2.xml

<?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:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</console>
	</appenders>
	<loggers>
		<root level="INFO">
			<appender-ref ref="Console" />
		</root>
	</loggers>
</configuration>

3. 调用代码

FluxWebClient.java

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.***mons.lang3.RandomUtils;
import org.apache.***mons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;

import lombok.extern.slf4j.Slf4j;

/**
 * WebClient是RestTemplete的替代品,有更好的响应式能力,支持异步调用<br>
 * 
 * https://blog.csdn.***/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("https://00fly.online/upload/urls.txt").a***eptCharset(StandardCharsets.UTF_8).a***ept(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)
                .a***eptCharset(StandardCharsets.UTF_8)
                .a***ept(MediaType.TEXT_HTML)
                .retrieve()
                .bodyToMono(String.class)
                .subscribe(r -> log.info("process ***plted: {}. {}", count.incrementAndGet(), url), e -> log.error(e.getMessage())));
        log.info("total:{} ==> ############## 异步请求已提交 ##############", urls.size());
    }
}

RunMain.java

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!");
    }
}

4. 运行结果

三,完整代码

如何使用下面的备份文件恢复成原始的项目代码,请移步查阅:神奇代码恢复工具

//goto pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>***.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.***ty</groupId>
			<artifactId>reactor-***ty</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.***mons</groupId>
			<artifactId>***mons-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-***piler-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="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
									<mainClass>***.fly.http.RunWebClient</mainClass>
								</transformer>
							</transformers>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>
//goto src\main\java\***\fly\http\FluxWebClient.java
package ***.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.***mons.lang3.RandomUtils;
import org.apache.***mons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;

import lombok.extern.slf4j.Slf4j;

/**
 * WebClient是RestTemplete的替代品,有更好的响应式能力,支持异步调用<br>
 * 
 * https://blog.csdn.***/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("https://00fly.online/upload/urls.txt").a***eptCharset(StandardCharsets.UTF_8).a***ept(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)
                .a***eptCharset(StandardCharsets.UTF_8)
                .a***ept(MediaType.TEXT_HTML)
                .retrieve()
                .bodyToMono(String.class)
                .subscribe(r -> log.info("process ***plted: {}. {}", count.incrementAndGet(), url), e -> log.error(e.getMessage())));
        log.info("total:{} ==> ############## 异步请求已提交 ##############", urls.size());
    }
}

//goto src\main\java\***\fly\http\RunMain.java
package ***.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\log4j2.xml
<?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:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</console>
	</appenders>
	<loggers>
		<root level="INFO">
			<appender-ref ref="Console" />
		</root>
	</loggers>
</configuration>


有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

转载请说明出处内容投诉
CSS教程_站长资源网 » 最简WebClient 同步、异步调用示例

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买