的释放
为了确保系统资源的释放,必须关闭与实体相关的内容流或者response自身:
package httpclienttest;
?
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
?
public class T7 {
? ? public static void main(String[] args) {
? ? ? ? CloseableHttpClient httpclient = HttpClients.createDefault();
? ? ? ? HttpGet httpget = new HttpGet("http://ifeng.com");
? ? ? ? //使用java7中的语法,自动调用close()方法,所以这里没有显示调用
? ? ? ? try(CloseableHttpResponse response = httpclient.execute(httpget)){
? ? ? ? ? ? HttpEntity entity = response.getEntity();
? ? ? ? ? ? try(BufferedReader reader = new BufferedReader(new InputStreamReader(
? ? ? ? ? ? ? ? ? ? entity.getContent(),StandardCharsets.UTF_8))){
? ? ? ? ? ? ? ? Stream sm = reader.lines();
? ? ? ? ? ? ? ? sm.forEach(System.out::println);
? ? ? ? ? ? }
? ? ? ? }catch(Exception e){
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
?
关闭内容流与关闭response之间的区别是,前者试图保持消费实体内容的基本连接是活的,而后者关闭连接并丢弃!请注意:一旦实体被完全写出,HttpEntity的writeTo(OutputStream)方法也要确保系统资源释放。如果调用HttpEntity的getContent()方法获得一个java.io.InputStream流的实例,在最后也是要关闭并释放资源的。
当使用流实体工作时,EntityUtils的consume(HttpEntity)方法能确保实体内容完全被消费掉,并自动后台关闭流来释放资源。
有种极少见的情况,请求响应的实体内容只有一小部分需要被检索,剩下的都不需要,而消费剩下的内容又有性能损耗,造成重用连接很高。这种情况下,可以直接关闭response来终止内容流!如下例:
package httpclienttest;
?
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
?
public class T8 {
? ? public static void main(String[] args) {
? ? ? ? CloseableHttpClient httpclient = HttpClients.createDefault();
? ? ? ? HttpGet httpget = new HttpGet("http://ifeng.com");
? ? ? ? try (CloseableHttpResponse response = httpclient.execute(httpget)) {
? ? ? ? ? ? HttpEntity entity = response.getEntity();
? ? ? ? ? ? if (entity != null) {
? ? ? ? ? ? ? ? InputStream instream = entity.getContent();
? ? ? ? ? ? ? ? int byteOne = instream.read();
? ? ? ? ? ? ? ? int byteTwo = instream.read();
? ? ? ? ? ? ? ? System.out.printf("%d,%d",byteOne,byteTwo);
? ? ? ? ? ? ? ? // instream中剩下的内容不需要了!直接关闭response
? ? ? ? ? ? }
? ? ? ? }catch(Exception e){
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
?
这样连接不会被重用,而且所有级别的资源都会被释放!
6. 消费实体内容
消费实体内容的推荐方式是使用HttpEntity的getContent()或HttpEntity的writeTo(OutputStream)方法。HttpClient还配备了EntityUtils类,它提供了几个静态方法让读取实体内容与信息更容易,而不是直接读java.io.InputStream。能通过EntityUtils的这些静态方法检索整个内容体到这符串/字节数组。不管怎样,强烈建议不要使用EntityUtils,除非响应实体产生自一个可信的HTTP服务端并且知道是有限长度的。示例:
?
package httpclienttest;
?
import java.nio.charset.StandardCharsets;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
?
public class T9 {
? ? public static void main(String[] args) {
? ? ? ? CloseableHttpClient httpclient = HttpClients.createDefault();
? ? ? ? HttpGet httpget = new HttpGet("http://www.