ApacheHttpClient和默认实现的比较
- Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection。
- ApacheHttpClient实现了连接池,同时它封装了访问http的请求头,参数,内容体,响应等等,使客户端发送 HTTP 请求变得容易。
ApacheHttpClient 使用
maven 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>10.1.0</version>
</dependency>
配置文件的修改
feign:
httpclient:
enabled: true
创建ApacheHttpClient客户端
import javax.net.ssl.SSLContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.springframework.util.ResourceUtils;
import feign.httpclient.ApacheHttpClient;
@Slf4j
public class FeignClientBuilder {
private boolean enabled;
private String keyPassword;
private String keyStore;
private String keyStorePassword;
private String trustStore;
private String trustStorePassword;
private int maxConnTotal = 2048;
private int maxConnPerRoute = 512;
public FeignClientBuilder(boolean enabled, String keyPassword, String keyStore, String keyStorePassword, String trustStore, String trustStorePassword, int maxConnTotal, int maxConnPerRoute) {
this.enabled = enabled;
this.keyPassword = keyPassword;
this.keyStore = keyStore;
this.keyStorePassword = keyStorePassword;
this.trustStore = trustStore;
this.trustStorePassword = trustStorePassword;
/**
* maxConnTotal是同时间正在使用的最多的连接数
*/
this.maxConnTotal = maxConnTotal;
/**
* maxConnPerRoute是针对一个域名同时间正在使用的最多的连接数
*/
this.maxConnPerRoute = maxConnPerRoute;
}
public ApacheHttpClient apacheHttpClient() {
CloseableHttpClient defaultHttpClient = HttpClients.custom()
.setMaxConnTotal(maxConnTotal)
.setMaxConnPerRoute(maxConnPerRoute)
.build();
ApacheHttpClient defaultApacheHttpClient = new ApacheHttpClient(defaultHttpClient);
if (!enabled) {
return defaultApacheHttpClient;
}
SSLContextBuilder sslContextBuilder = SSLContexts.custom();
// 如果 服务端启用了 TLS 客户端验证,则需要指定 keyStore
if (keyStore == null || keyStore.isEmpty()) {
return new ApacheHttpClient();
} else {
try {
sslContextBuilder
.loadKeyMaterial(
ResourceUtils.getFile(keyStore),
keyStorePassword.toCharArray(),
keyPassword.toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
}
// 如果 https 使用自签名证书,则需要指定 trustStore
if (trustStore == null || trustStore.isEmpty()) {
} else {
try {
sslContextBuilder
// .loadTrustMaterial(TrustAllStrategy.INSTANCE)
.loadTrustMaterial(
ResourceUtils.getFile(trustStore),
trustStorePassword.toCharArray()
);
} catch (Exception e) {
e.printStackTrace();
}
}
try {
SSLContext sslContext = sslContextBuilder.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpClient = HttpClients.custom()
.setMaxConnTotal(maxConnTotal)
.setMaxConnPerRoute(maxConnPerRoute)
.setSSLSocketFactory(sslsf)
.build();
ApacheHttpClient apacheHttpClient = new ApacheHttpClient(httpClient);
log.info("feign Client load with ssl.");
return apacheHttpClient;
} catch (Exception e) {
e.printStackTrace();
}
return defaultApacheHttpClient;
}
public static FeignClientBuilderBuilder builder() {
return new FeignClientBuilderBuilder();
}
public static class FeignClientBuilderBuilder {
private boolean enabled;
private String keyPassword;
private String keyStore;
private String keyStorePassword;
private String trustStore;
private String trustStorePassword;
private int maxConnTotal = 2048;
private int maxConnPerRoute = 512;
public FeignClientBuilderBuilder enabled(boolean enabled) {
this.enabled = enabled;
return this;
}
public FeignClientBuilderBuilder keyPassword(String keyPassword) {
this.keyPassword = keyPassword;
return this;
}
public FeignClientBuilderBuilder keyStore(String keyStore) {
this.keyStore = keyStore;
return this;
}
public FeignClientBuilderBuilder keyStorePassword(String keyStorePassword) {
this.keyStorePassword = keyStorePassword;
return this;
}
public FeignClientBuilderBuilder trustStore(String trustStore) {
this.trustStore = trustStore;
return this;
}
public FeignClientBuilderBuilder trustStorePassword(String trustStorePassword) {
this.trustStorePassword = trustStorePassword;
return this;
}
public FeignClientBuilderBuilder maxConnTotal(int maxConnTotal) {
this.maxConnTotal = maxConnTotal;
return this;
}
public FeignClientBuilderBuilder maxConnPerRoute(int maxConnPerRoute) {
this.maxConnPerRoute = maxConnPerRoute;
return this;
}
public FeignClientBuilder build() {
return new FeignClientBuilder(
this.enabled,
this.keyPassword,
this.keyStore,
this.keyStorePassword,
this.trustStore,
this.trustStorePassword,
this.maxConnTotal,
this.maxConnPerRoute
);
}
}
}
使用时可以直接使用builder来创建ApacheHttpClient。