HttpClient实现网络访问详解1

1、HttpClient的最常用功能是execute()方法。执行一次execute()会包括了一次或多次request请求 - response响应事件。HttpClient会将request请求发送给目标服务器以取得response响应对象,也可有可能在执行失败后抛出一个异常。

一个简单的代码如下:

CloseableHttpClienthttpclient = HttpClients.createDefault();
    HttpGet httpget = newHttpGet("http://localhost/");
    CloseableHttpResponse response = httpclient.execute(httpget);
    try {
        <...>
    } finally {
        response.close();
    }

2、所有的Http request请求都包括了一个方法名、一个请求地址和一个HTTP协议版本号。HttpClient支持HTTP/1.1协议下所有的HTTP方法,包括:Get、HEAD、POST、PUT、DELETE、TRACE和OPTIONS。每一种方法都通过特定的类来实现,包括HttpGet、HttpHead、HttpPost、HttpPut、HttpDelete、HttpTrace和HttpOptions。

请求地址由一个URI(统一资源定位符)来描述。Http URI包括了协议、主机名、端口、地址、请求参数等。

例如:

HttpGet httpget = newHttpGet(
     "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");

HttpClient 提供了URIBuilder类来简化请求地址的创建和修改,例如:

URI uri = newURIBuilder()
           .setScheme("http")
           .setHost("www.google.com")
           .setPath("/search")
           .setParameter("q","httpclient")
           .setParameter("btnG","Google Search")
           .setParameter("aq","f")
           .setParameter("oq","")
           .build();
    HttpGet httpget = new HttpGet(uri);
    System.out.println(httpget.getURI());

输出:

http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=

3、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());

4、一段Http报文包括了多个header描述属性,包括内容长度、内容类型等等,HttpClient提供了查询、删除、处理header的方法,例如:

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);

输出:

Set-Cookie: c1=a;path=/; domain=localhost
    Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
    2

最有效率的做法是用HeaderIterator来获得特定类型的所有header。

例如:

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\"");

HeaderIterator it =response.headerIterator("Set-Cookie");

while (it.hasNext()){
            System.out.println(it.next());
    }

输出:

Set-Cookie: c1=a;path=/; domain=localhost
    Set-Cookie: c2=b; path="/", c3=c; domain="localhost"

5、HttpEntity 是Http request-reponse交互的报文内容。HttpClient区分了三种报文内容:

(1)流形式的报文内容,报文内容不可重复。

(2)独立的报文内容,报文内容是可重复的。

(3)从其他报文内容中获取的报文内容。

通过HttpEntity的getContent()可以获得Java.io.Inputstream的输入流,也可以通过HttpEntity的writeTo(OutputStream)写入内容。

HttpEntity的getContentType()和getContentLength()方法可以获取Content-Type和Content-Length的元数据,getContentEncoding()方法可以获取编码格式。

例如:

StringEntity myEntity= new StringEntity("important message",
    ContentType.create("text/plain", "UTF-8"));

System.out.println(myEntity.getContentType());
    System.out.println(myEntity.getContentLength());
    System.out.println(EntityUtils.toString(myEntity));
    System.out.println(EntityUtils.toByteArray(myEntity).length);

输出:

Content-Type:text/plain; charset=utf-8
    17
    important message
    17

读取HttpEntity,例如:

CloseableHttpClienthttpclient = HttpClients.createDefault();
    HttpGet httpget = newHttpGet("http://localhost/");
    CloseableHttpResponse response = httpclient.execute(httpget);
    try {
        HttpEntity entity =response.getEntity();
        if (entity != null) {
            long len =entity.getContentLength();
            if (len != -1 && len <2048) {
               System.out.println(EntityUtils.toString(entity));
            } else {
                // Stream contentout
            }
        }
    } finally {
        response.close();
    }

也可以生成报文内容

File file = newFile("somefile.txt");
    FileEntity entity = new FileEntity(file,
                       ContentType.create("text/plain", "UTF-8"));

HttpPost httppost =newHttpPost("http://localhost/action.do");
    httppost.setEntity(entity);

6、可以通过UrlEncodeFormEntity来提交表单,例如

List<NameValuePair>formparams = new ArrayList<NameValuePair>();
    formparams.add(new BasicNameValuePair("param1","value1"));
    formparams.add(new BasicNameValuePair("param2","value2"));
    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams,Consts.UTF_8);
    HttpPost httppost = newHttpPost("http://localhost/handler.do");
    httppost.setEntity(entity);

7、可以采用ResponseHandler来简化连接操作,例如

CloseableHttpClienthttpclient = HttpClients.createDefault();
    HttpGet httpget = new HttpGet("http://localhost/json");

ResponseHandler<MyJsonObject>rh = new ResponseHandler<MyJsonObject>() {

@Override
        public JsonObjecthandleResponse(
                final HttpResponse response)throws IOException {
            StatusLine statusLine =response.getStatusLine();
            HttpEntity entity =response.getEntity();
            if (statusLine.getStatusCode()>= 300) {
                throw newHttpResponseException(
                   statusLine.getStatusCode(),
                    statusLine.getReasonPhrase());
            }
            if (entity == null) {
                throw newClientProtocolException("Response contains no content");
            }
            Gson gson = newGsonBuilder().create();
            ContentType contentType =ContentType.getOrDefault(entity);
            Charset charset =contentType.getCharset();
            Reader reader = newInputStreamReader(entity.getContent(), charset);
            return gson.fromJson(reader,MyJsonObject.class);
        }
    };
    MyJsonObject myjson = client.execute(httpget, rh);

8、 httpClient不是线程安全的,所以如果不再使用的话,可以通过close()方法进行关闭,例如

CloseableHttpClienthttpclient = HttpClients.createDefault();
    try {
        <...>
    } finally {
            httpclient.close();
}

9、HttpContext可以作为Http交互的上下文,是以java.util.Map存储的对象。包括了HttpConnection、HttpHost、HttpRoute、HttpRequest等,可以通过HttpclientContext来定义上下文状态。

HttpContext context =<...>
    HttpClientContext clientContext =HttpClientContext.adapt(context);
    HttpHost target = clientContext.getTargetHost();
    HttpRequest request = clientContext.getRequest();
    HttpResponse response = clientContext.getResponse();
    RequestConfig config = clientContext.getRequestConfig();

10、如果要实现重试机制,可以采用HttpRequestRetryHandler接口来实现。例如:

HttpRequestRetryHandlermyRetryHandler = new HttpRequestRetryHandler() {

public booleanretryRequest(
                IOExceptionexception,
                intexecutionCount,
                HttpContext context){
        if (executionCount >= 5){
            // Do not retry if over maxretry count
            return false;
        }
        if (exception instanceofInterruptedIOException) {
            // Timeout
            return false;
        }
        if (exception instanceofUnknownHostException) {
            // Unknown host
            return false;
        }
        if (exception instanceofConnectTimeoutException) {
            // Connectionrefused
            return false;
        }
        if (exception instanceofSSLException) {
            // SSL handshakeexception
            return false;
        }
        HttpClientContext clientContext =HttpClientContext.adapt(context);
        HttpRequest request =clientContext.getRequest();
        boolean idempotent = !(requestinstanceof HttpEntityEnclosingRequest);
        if (idempotent) {
            // Retry if the request isconsidered idempotent
            return true;
        }
            return false;
        }

};
    CloseableHttpClient httpclient = HttpClients.custom()
               .setRetryHandler(myRetryHandler)
                .build();

11、重定向处理,例如:

CloseableHttpClienthttpclient = HttpClients.createDefault();
    HttpClientContext context = HttpClientContext.create();
    HttpGet httpget = newHttpGet("http://localhost:8080/");
    CloseableHttpResponse response = httpclient.execute(httpget, context);
    try {
        HttpHost target =context.getTargetHost();
        List<URI> redirectLocations =context.getRedirectLocations();
        URI location =URIUtils.resolve(httpget.getURI(), target, redirectLocations);
        System.out.println("Final HTTPlocation: " + location.toASCIIString());
        // Expected to be an absoluteURI
    } finally {
        response.close();
    }

时间: 2024-10-10 01:03:47

HttpClient实现网络访问详解1的相关文章

Kafka集群常见的跨网络访问详解

场景说明:当客户端与服务端在不同区域(跨防火墙,地址均做了映射)时,客户端访问kafka时会出现获取不到broker的问题,但是网络之间是互通的.但在跨防火墙下,client请求zookeeper的时候,zookeeper返回给client的broker IP是kafka的实际地址,而不是映射地址,因此client会访问失败. 解决方式一.1.配置文件:listeners=PLAINTEXT://主机名:90922.服务端hosts:内网地址 主机名 3.客户端hosts :外网地址 主机名 注

虚拟机的几种网络方式详解

虚拟机的几种网络方式详解本部分作为2部分进行讲解1.虚拟机常见的上网模式详细解析2.在使用虚拟机中常见的问题处理 先看问题1虚拟机常见的上网模式详细解析虚拟机就是利用真实机的环境用软件的方式模拟成类似真实机系统的一个软件,现在主流的有微软的虚拟机,有vmare,orcale virtualBOx(orcale  virtualBOx原名叫做Sun virtualBOx 前不久刚被orcale公司收购所以改名为orcale  virtualBOx)那么不管是那种虚拟机,在虚拟机软件都内置了几种虚拟

ContentProvider数据访问详解

ContentProvider数据访问详解 Android官方指出的数据存储方式总共有五种:Shared Preferences.网络存储.文件存储.外储存储.SQLite,这些存储方式一般都只是在一个单独的应用程序中实现数据的共享,而对于需要操作其他应用程序中的数据时(如媒体库.通讯录等),可能就需要借助ContentProvider了. 1.ContentProvider ContentProvider为存储和获取数据提供了统一的接口,使用表的形式来对数据进行封装,使得开发者在后续的开发过程

Docker基础 :网络配置详解

本篇文章将讲述 Docker 的网络功能,包括使用端口映射机制来将容器内应用服务提供给外部网络,以及通过容器互联系统让多个容器之间进行快捷的网络通信,有兴趣的可以了解下. 大量的互联网应用服务包含多个服务组件,这往往需要多个容器之间通过网络通信进行相互配合.Docker 目前提供了映射容器端口到宿主主机和容器互联机制来为容器提供网络服务.接下来我们将讲述 Docker 的网络功能,包括使用端口映射机制来将容器内应用服务提供给外部网络,以及通过容器互联系统让多个容器之间进行快捷的网络通信. 端口映

Docker:网络模式详解

Docker作为目前最火的轻量级容器技术,牛逼的功能,如Docker的镜像管理,不足的地方网络方面. Docker自身的4种网络工作方式,和一些自定义网络模式 安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络). none .host.Container host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口. Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP.端口范围. None:该模式关

用netstat查看网络状态详解

--用netstat查看网络状态详解 -----------------------------2014/06/11 一.Linux服务器上11种网络连接状态:                                          图:TCP的状态机 通常情况下:一个正常的TCP连接,都会有三个阶段:1.TCP三次握手;2.数据传送;3.TCP四次挥手 注:以下说明最好能结合"图:TCP的状态机"来理解. SYN: (同步序列编号,Synchronize Sequence

Java网络编程详解

Java网络编程详解 http://blog.csdn.net/he90227/article/details/39184247 Java网络编程详解

Linux网络配置详解

1.前言 对于LINUX而言,如果我们想对其进行网络配置的话,那么主要涉及到如下方面的配置: IP,子网掩码,网关,主机名,DNS服务器地址,路由信息. 那么下面,将对这些方面进行操作配置.如果大家对网络的有关知识,不太清楚的,可以参考我的博客:http://zhangfengzhe.blog.51cto.com/8855103/1438163 [这篇博客将快速让大家了解一些概念] 2.关于ifconfig [[email protected] ~]# ifconfig eth0      Li

sentos 网络配置文件详解

网卡配置文件说明: ################################ [[email protected] ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 ==>这里是eth0网卡设备的默认配置文件# Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]DEVICE=eth0 ================>这里是网卡名称第一块网卡为eth0,第二块为eth1...BOOTP