HttpClient 该知道一些概念
HttpClient 该知道不该知道的一些事
一、简介:
- Apache开源项目: http://hc.apache.org/
- 基于HTTP协议提供强大的支持,构建HTTP客户端应用程序
- 执行HTTP协议时,包含了HTTP请求和响应不同状态,可以对关键参数设置和获取
二、HTTP协议(扫盲)
- HTTP请求包含三部分,分别由请求行(请求方法)、请求头(消息报文)、请求正文组成。
- HTTP请求详解:

- HTTP 响应详解

三、URI URL和URN区别:
- URI(Uniform Resource Identifier) 统一资源标识符
- URL(Uniform Resource Locator) 统一资源定位符
- URN(Uniform Resource Name) 统一资源名称
- 整体关系:

- 举个栗子么:
比如有一个虚拟地址,首先这是一个URI:
xxxxxxxxxx1
1
http://bitpoetry.io/posts/hello.html#intro我们分析:
xxxxxxxxxx1
1
http:// 是定义如何访问资源的方式。
xxxxxxxxxx1
1
bitpoetry.io/posts/hello.html是资源存放的位置,那么,在这个栗子中,
xxxxxxxxxx1
1
#intro是资源。
- URL是URI的一个子集,告诉我们访问网络位置的方式,
xxxxxxxxxx1
1
http://bitpoetry.io/posts/hello.html- URN是URI的子集,包括名字(给定的命名空间内),但不包括访问方式
xxxxxxxxxx1
1
bitpoetry.io/posts/hello.html#intro- 创建 HttpClient 对象
- 创建请求方法的实例,并指定URL。
- GET 请求,创建 HttpGet 对象
- POST 请求,创建 HttpPost 对象
- 调用 SetParams(HttpParams params) 方法来添加请求参数, 对于 HttpPost 对象而言,也可以调用 setEntity(HttpEntity entity) 方法来设置请求参数
- 调用 HttpClient 对象的 execute(HttpUriRequest request) 发送请求,该方法返回一个 HttpResponse
- 调用 HttpResponse 的 getAllHeaders()、getHeaders(String name) 等方法可获取服务器的响应头;调用 HttpResponse 的 getEntity() 方法可获取 HttpEntity 对象,该对象包装了服务器的相应内容。程序可以通过获取服务器的相应内容
- 释放连接,无论执行方法是否成功,都必须释放连接
例如下图:

五、调用细节:
- HttpClient提供了URIBuilder类来简化和修改请求URI
xxxxxxxxxx1
1
http://image.baidu.com/search/detail?ct=503316480&word=scheme 可以有如下写法:
xxxxxxxxxx7
1
URI uri = new URIBuilder()2
.setScheme("http") //设置scheme3
.setHost("image.baidu.com")//set host4
.setPath("/search/detail")// set path5
.setParameter("ct","503316480")// set param6
.setParameter("word","scheme")7
.build();- 在Response中几个关键参数获取:
xxxxxxxxxx3
1
response.getProtocolVersion() // 协议2
response.getStatusLine().getStatusCode() //状态码3
response.getStatusLine().getReasonPhrase()//表单含义- 获取给定类型的所有头部信息最有效的方式是使用HeaderIterator接口:
xxxxxxxxxx30
1
public static void main(String[] args) {2
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");3
response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost");4
response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\"");5
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie"));6
while (it.hasNext()) {7
HeaderElement elem = it.nextElement(); 8
System.out.println(elem.getName() + " = " + elem.getValue());9
NameValuePair[] params = elem.getParameters();10
for (int i = 0; i < params.length; i++) {11
System.out.println(" " + params[i]);12
}13
}14
}15
16
运行输出:17
18
c1 = a19
20
path=/21
22
domain=localhost23
24
c2 = b25
26
path=/27
28
c3 = c29
30
domain=localhost- 为了保证系统资源被正确地释放,我们要么管理HTTP实体流,要么关闭http响应。
- 关闭HTTP实体内容流和关闭HTTP响应的区别,前者通过消耗掉HTTP实体内容来保持相关HTTP连接,然而后者会立即关闭,丢弃HTTP连接。
- HttpClient 推荐使用 HttpEntity 的 getContent() 方法或者 HttpEntity 的 writeTo(OutputStream) 方法读取Http实体内容。
- EntityUtils 提供的方法可以以字符串或者字节数组的形式读取 Http 实体,但是一般不建议,确保相应的实体长度不大。
- 希望把 Http 实体内容缓存在内存或者磁盘上,最简单方法就是把 Http Entity 转化为 BufferedHttpEntity,
xxxxxxxxxx5
1
CloseableHttpResponse response = <...>2
HttpEntity entity = response.getEntity();3
if (entity != null) {4
entity = new BufferedHttpEntity(entity);5
}- HttpClient 提供了一些类,这些类可以通过http连接高效地输出Http实体内容。
- HttpClient 提供的这几个类涵盖的常见的数据类型,如String,byte 数组,输入流,和文件类型:StringEntity,ByteArrayEntity,InputStreamEntity,FileEntity。
xxxxxxxxxx6
1
File file = new File("somefile.txt");2
FileEntity entity = new FileEntity(file, 3
ContentType.create("text/plain", "UTF-8")); 4
5
HttpPost httppost = new HttpPost("http://localhost/action.do");6
httppost.setEntity(entity);- 请注意由于 InputStreamEntity 只能从下层的数据流中读取一次,所以它是不能重复的。推荐,通过继承 HttpEntity 这个自包含的类来自定义HttpEntity 类,而不是直接使用 InputStreamEntity 这个类。FileEntity 就是一个很好的起点(FileEntity 就是继承的 HttpEntity)。
- 模拟 HTML 表单提交
xxxxxxxxxx6
1
List<NameValuePair> formparams = new ArrayList<NameValuePair>();2
formparams.add(new BasicNameValuePair("param1", "value1"));3
formparams.add(new BasicNameValuePair("param2", "value2"));4
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);5
HttpPost httppost = new HttpPost("http://localhost/handler.do");6
httppost.setEntity(entity);- 设置传输编码方式(1.0不支持)
xxxxxxxxxx1
StringEntity entity = new StringEntity("important message",2
ContentType.create("plain/text", Consts.UTF_8));3
entity.setChunked(true);4
HttpPost httppost = new HttpPost("http://localhost/acrtion.do");5
httppost.setEntity(entity);- 处理http响应的方法就是使用ResponseHandler接口,这个接口中有handleResponse(HttpResponse response)方法。使用这个方法,用户完全不用关心http连接管理器。当使用ResponseHandler时,HttpClient会自动地将Http连接释放给Http管理器,即使http请求失败了或者抛出了异常。
xxxxxxxxxx26
1
CloseableHttpClient httpclient = HttpClients.createDefault();2
HttpGet httpget = new HttpGet("http://localhost/json");3
4
ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() {5
6
7
public JsonObject handleResponse(8
final HttpResponse response) throws IOException {9
StatusLine statusLine = response.getStatusLine();10
HttpEntity entity = response.getEntity();11
if (statusLine.getStatusCode() >= 300) {12
throw new HttpResponseException(13
statusLine.getStatusCode(),14
statusLine.getReasonPhrase());15
}16
if (entity == null) {17
throw new ClientProtocolException("Response contains no content");18
}19
Gson gson = new GsonBuilder().create();20
ContentType contentType = ContentType.getOrDefault(entity);21
Charset charset = contentType.getCharset();22
Reader reader = new InputStreamReader(entity.getContent(), charset);23
return gson.fromJson(reader, MyJsonObject.class);24
}25
};26
MyJsonObject myjson = client.execute(httpget, rh);
浙公网安备 33010602011771号