简单介绍
HTTP 的全称是Hypertext Transfer Protocol Vertion (超文本传输协议),就是用网络链接传输文本信息的协议,是现在互联网中广泛使用的协议。
除了 HTTP 协议,还有 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer)协议,它是在 HTTP 下加入SSL层,以用来进行安全的 HTTP 数据传输,可以说是 HTTP 的安全版。
这里使用 JAVA 语言,参照Apache HttpClient的官网,总结了 HttpClient 的一些关于 HTTP 请求的使用,方便以后使用。
使用
HTTP 请求
发起 HTTP 请求首先要有请求的 URI :
- 可以直接使用 HttpGet 的构造方法:
HttpGet httpget = new HttpGet("http://www.google.com/search?hl=en&&btnG=Google+Search&aq=f&oq=");
- 也可以使用HttpClient提供URIBuilder:
URI uri = new URIBuilder()
.setScheme("http")
.setHost("www.google.com")
.setPath("/search")
.setParameter("btnG", "Google Search")
.setParameter("aq", "f")
.setParameter("oq", "")
.build();
HttpGet httpget = new HttpGet(uri);
// 打印URL最后的完整名称
System.out.println(httpget.getURI());
//显示结果:http://www.google.com/search?&btnG=Google+Search&aq=f&oq=
有了 URI 就可以发起简单的 HTTP 请求了:
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(target,request);
System.out.println("网络请求: "+response1.toString());
//发起一次网络请求就会建立一次网络连接这很占资源,所以最后在不用时最后释放掉
esponse.close();
httpclient.close();
在成功接收请求消息之后服务器会发送回客户端的消息-HttpResponse ,该消息的第一行中包括协议版本,数字状态代码及其关联的文本短语:
//构建一个返回数据
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
HttpStatus.SC_OK, "OK");
//协议版本
System.out.println(response.getProtocolVersion());
//返回的状态码
System.out.println(response.getStatusLine().getStatusCode());
//返回状态码关联文本
System.out.println(response.getStatusLine().getReasonPhrase());
//服务器返回的数据中第一行完整字符串
System.out.println(response.getStatusLine().toString());
返回结果如下:
HTTP/1.1
200
OK
HTTP/1.1 200 OK
对于服务端返回的数据中有描述消息属性的多个头部,如内容长度,内容类型等。HttpClient也提供了对这些内容的检索,添加,删除和枚举头文件的方法。
//构建一个返回数据
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie","c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie","c2=b; path=\"/\", c3=c; domain=\"localhost\"");
//过去消息头数据
Header h1 = response.getFirstHeader("Set-Cookie");
System.out.println(h1);
Header h2 = response.getLastHeader("Set-Cookie");
System.out.println(h2);
Header[] hs = response.getHeaders("Set-Cookie");
System.out.println(hs.length);
当然,HttpResponse 还提供了 HeaderIterator 方法用来遍历所有标头:
HeaderIterator it = response.headerIterator("Set-Cookie");
while (it.hasNext()) {
System.out.println(it.next());
}
接下来就是获取服务器返回的数据的主要文本信息了,HttpEntity
entity就是发送或者接收消息的载体,entity可以从 request 和 response 中获取:
HttpEntity entity = response.getEntity();
//打印返回的状态
System.out.println(response.getStatusLine());
if (entity != null) {
//打印返回的内容长度
System.out.println("Response content length: " + entity.getContentLength());
//打印返回的数据内容
System.out.println("Response content: " + EntityUtils.toString(entity));
}
使用代理发起 HTTP 请求
即使HttpClient知道复杂的路由方案和代理链接,它只支持简单的直接或一跳代理连接开箱即用。
告诉HttpClient通过代理连接到目标主机的最简单方法是设置默认代理参数:
// "127.0.0.1", 8087 为代理的host 和 port
HttpHost proxy = new HttpHost("127.0.0.1", 8087);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CloseableHttpClient httpclient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();
还可以指示 HttpClient 使用标准的JRE代理选择器来获取代理信息:
SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(
ProxySelector.getDefault());
CloseableHttpClient httpclient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();
或者,可以提供自定义RoutePlanner 实现,以便完全控制HTTP路由计算的过程:
HttpRoutePlanner routePlanner = new HttpRoutePlanner() {
public HttpRoute determineRoute(
HttpHost target,
HttpRequest request,
HttpContext context) throws HttpException {
// "127.0.0.1", 8087 为代理的host 和 port
return new HttpRoute(target, null, new HttpHost("127.0.0.1", 8087),
"https".equalsIgnoreCase(target.getSchemeName()));
}
};
CloseableHttpClient httpclient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();
}
}
发起 HTTPS 请求
想要发起SSL请求,需要创建 SSL 连接
/**
* 创建 SSL连接
* @return
* @throws GeneralSecurityException
*/
private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null,
new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (GeneralSecurityException e) {
throw e;
}
}
设置好 SSL 连接就可以发起 HTTPS 请求了:
CloseableHttpClient httpclient = createSSLInsecureClient();
HttpGet httpget = new HttpGet("https://www.baidu.com/");
System.out.println("Executing request " + httpget.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(response.toString());
System.out.println("entity:");
System.out.println(EntityUtils.toString(entity, "utf-8"));
// 确保实体内容被完全消费,并且内容流(如果存在)被关闭。
EntityUtils.consume(entity);
} finally {
response.close();
httpclient.close();
}
}
最后一个就是使用代理发起 HTTPS 请求:
(我试过不使用SSL连接创建CloseableHttpClient (使用 HttpClients.createDefault()方式),使用这样方式的代理,但是会报错:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 原因可以查看文章 unable to find valid certification path to requested target):
public static void httpsUseProxy() {
CloseableHttpClient httpclient = null;
try {
CloseableHttpClient httpclient = createSSLInsecureClient();
HttpHost target = new HttpHost("www.google.com", 443, "https");
// "127.0.0.1", 8087 为代理的host 和 port
HttpHost proxy = new HttpHost("127.0.0.1", 8087, "http");
RequestConfig config = RequestConfig.custom().setProxy(proxy)
// HTTP连接超时时间
.setConnectTimeout(5000)
// HTTP请求超时时间
.setConnectionRequestTimeout(5000)
// HTTP套接字SOCKET超时时间
.setSocketTimeout(5000).build();
HttpGet request = new HttpGet("/");
request.setConfig(config);
System.out.println("Executing request " + request.getRequestLine() + " to " + target + " via " + proxy);
CloseableHttpResponse response = httpclient.execute(target, request);
System.out.println("--服务端返回的数据状态信息-------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
response.close();
} catch(IOException e){
} catch (GeneralSecurityException e) {
}finally {
httpclient.close();
}
}
总结
之前项目需要,要使用 JAVA 发起HTTP 和 HTTPS 请求。由于公司要使用代理才可以上网,所以在网上看Apache 的 HttpClient 官方文档才有了这文章。
这里只是总结了一下 HttpClient 的 HTTP , HTTPS 请求以及使用代理的简单使用,通过官方文档,发现 HttpClient 还有很多很多的用法,以后有需要时在总结吧。