作为一个Java开发,相信大家都用过HttpClient去请求外部资源,而在用的时候都是直接在网上Copy工具类,直接调用,而我们不用不了解Client中的一些参数是怎么配置的。所以在出问题了的时候都束手无策。本文就和大家一起从官网的实例去了解HttpClient 的一些基本配置。
在此之前我先把我看过示例之后自己写的工具类分享出来:工具类HttpRequests,点击下载
欢迎下载使用,更希望自己动动手,写一下。
一、查看官网示例
这里我使用的版本是4.5。
示例思想:
示例源码(结合上面思想和代码注释):
public final static void main(String[] args) throws Exception {
// Use custom message parser / writer to customize the way HTTP
// messages are parsed from and written out to the data stream.
/**通过用户消息解析器/写入器自定义解析http响应的数据流*/
/**响应解析器*/
HttpMessageParserFactory<HttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() {
@Override
public HttpMessageParser<HttpResponse> create(SessionInputBuffer buffer, MessageConstraints constraints) {
LineParser lineParser = new BasicLineParser() {
@Override
public Header parseHeader(final CharArrayBuffer buffer) {
try {
return super.parseHeader(buffer);
} catch (ParseException ex) {
return new BasicHeader(buffer.toString(), null);
}
}
};
return new DefaultHttpResponseParser(
buffer, lineParser, DefaultHttpResponseFactory.INSTANCE, constraints) {
@Override
protected boolean reject(final CharArrayBuffer line, int count) {
// try to ignore all garbage preceding a status line infinitely
return false;
}
};
}
};
/**请求处理器*/
HttpMessageWriterFactory<HttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory();
// Use a custom connection factory to customize the process of
// initialization of outgoing HTTP connections. Beside standard connection
// configuration parameters HTTP connection factory can define message
// parser / writer routines to be employed by individual connections.
/**Http连接(从三次握手到四次挥手叫做一个连接)管理工厂*/
HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
requestWriterFactory, responseParserFactory);
// Client HTTP connection objects when fully initialized can be bound to
// an arbitrary network socket. The process of network socket initialization,
// its connection to a remote address and binding to a local one is controlled
// by a connection socket factory.
// SSL context for secure connections can be created either based on
// system or application specific properties.
/**配置默认HTTPS连接证书认证处理(这里可以有两种处理方式,配置证书给代码或者忽略,我的示例里边是使用忽略证书的方式),
* 并且丢到Socket里边,http是应用层协议,Socket是在处于应用层和网络层的连接工具(5层模式中)。所以这里是Socket认证证书*/
SSLContext sslcontext = SSLContexts.createSystemDefault();
// Create a registry of custom connection socket factories for supported
// protocol schemes.
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
// Use custom DNS resolver to override the system DNS resolution.
/**使用用户自定义DNS*/
DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
@Override
public InetAddress[] resolve(final String host) throws UnknownHostException {
if (host.equalsIgnoreCase("myhost")) {
return new InetAddress[] { InetAddress.getByAddress(new byte[] {127, 0, 0, 1}) };
} else {
return super.resolve(host);
}
}
};
// Create a connection manager with custom configuration.
/**上面的DNS, 连接工厂, socke工厂通过连接管理池来统一管理*/
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
socketFactoryRegistry, connFactory, dnsResolver);
// Create socket configuration
SocketConfig socketConfig = SocketConfig.custom()
.setTcpNoDelay(true)
.build();
// Configure the connection manager to use socket configuration either
// by default or for a specific host.
connManager.setDefaultSocketConfig(socketConfig);/**配置默认socket配置*/
connManager.setSocketConfig(new HttpHost("somehost", 80), socketConfig);/**配置特殊请求socket配置*/
// Validate connections after 1 sec of inactivity
connManager.setValidateAfterInactivity(1000); //连接池每秒检查一次连接是否活跃
// Create message constraints
/**自定义请求消息约束 具体什么约束查看字面意思就行*/
MessageConstraints messageConstraints = MessageConstraints.custom()
.setMaxHeaderCount(200)
.setMaxLineLength(2000)
.build();
// Create connection configuration
/**连接配置*/
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setMalformedInputAction(CodingErrorAction.IGNORE)
.setUnmappableInputAction(CodingErrorAction.IGNORE)
.setCharset(Consts.UTF_8)
.setMessageConstraints(messageConstraints)
.build();
// Configure the connection manager to use connection configuration either
// by default or for a specific host.
connManager.setDefaultConnectionConfig(connectionConfig);
connManager.setConnectionConfig(new HttpHost("somehost", 80), ConnectionConfig.DEFAULT);
// Configure total max or per route limits for persistent connections
// that can be kept in the pool or leased by the connection manager.
/**连接管理池大小配置*/
connManager.setMaxTotal(100);
connManager.setDefaultMaxPerRoute(10);
connManager.setMaxPerRoute(new HttpRoute(new HttpHost("somehost", 80)), 20);
// Use custom cookie store if necessary.
CookieStore cookieStore = new BasicCookieStore();
// Use custom credentials provider if necessary.
/**认证器(可以用于请求目标认证和poxy认证) 包含 host port 账号 密码*/
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope("127.0.0.1", 111), new UsernamePasswordCredentials("", ""));
// Create global request configuration
/**请求配置,这个是我们常用的*/
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setCookieSpec(CookieSpecs.DEFAULT)
.setExpectContinueEnabled(true)
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)) //首选认证方式配置
.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
.build();
// Create an HttpClient with the given custom dependencies and configuration.
/**创建httpClient*/
CloseableHttpClient httpclient = HttpClients.custom()
.setConnectionManager(connManager)
.setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credentialsProvider)
.setProxy(new HttpHost("myproxy", 8080))//使用代理
.setDefaultRequestConfig(defaultRequestConfig)
.build();
try {
/**实现一次请求*/
HttpGet httpget = new HttpGet("http://httpbin.org/get");
// Request configuration can be overridden at the request level.
// They will take precedence over the one set at the client level.
RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
.setSocketTimeout(5000)
.setConnectTimeout(5000)
.setConnectionRequestTimeout(5000) //上方三条超时配置
.setProxy(new HttpHost("myotherproxy", 8080)) //使用代理
.build();
httpget.setConfig(requestConfig);
// Execution context can be customized locally.
/**请求上下文--请求的所有东西都会放这里*/
HttpClientContext context = HttpClientContext.create();
// Contextual attributes set the local context level will take
// precedence over those set at the client level.
context.setCookieStore(cookieStore);
context.setCredentialsProvider(credentialsProvider);
System.out.println("executing request " + httpget.getURI());
CloseableHttpResponse response = httpclient.execute(httpget, context);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
System.out.println("----------------------------------------");
// Once the request has been executed the local context can
// be used to examine updated state and various objects affected
// by the request execution.
// Last executed request
context.getRequest();
// Execution route
context.getHttpRoute();
// Target auth state
context.getTargetAuthState();
// Proxy auth state
context.getProxyAuthState();
// Cookie origin
context.getCookieOrigin();
// Cookie spec used
context.getCookieSpec();
// User security token
context.getUserToken();
} finally {
response.close(); //管理响应的数据流
}
} finally {
httpclient.close(); //关闭httpClient
}
}
二、自己实现的HttpRequest工具类HttpRequests
依赖:
<!--HttpClient 工具-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<!-- 用于上传文件或者文件流 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.8</version>
</dependency>
代码解释:
如上两图,查看注释,一目了然。。。
源码链接在文章开头,欢迎下载!!!!!!!!!!!!!!!!!!!!!
三、工具类的使用
public static void main(String[] args) throws Exception {
//普通get请求
/*String result = HttpRequests.custom(HttpRequests.GET, "https://www.ip.cn/")
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36")
.build().request();
System.out.println(result);*/
//添加代理get请求
/*String result = HttpRequests.custom(HttpRequests.GET, "https://www.ip.cn/")
.setProxy("username::password@host:port")
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36")
.build().request();
System.out.println(result);*/
//post请求
/*String body = "[]";
String result = HttpRequests.custom(HttpRequests.POST, "http://localhost/admin")
.setContentType("application/json")
.setBody(body)
.build().request();
System.out.println(result);*/
//文件上传
String body = "{" +
"\"address\": \"C:\\Users\\30045\\Desktop\\my doc\\timg.jpg\"," +
"\"name\": \"uploadFile\"" +
"}";
String result = HttpRequests.custom(HttpRequests.FILE, "http://localhost/upload")
.setBody(body)
.build().request();
System.out.println(result);
}
欢迎留言讨论。。。。