• HttpClient研究学习总结


    Http协议非常的重要,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。

    一、Http简介

          HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。 

          HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。 
    HTTP协议的主要特点可概括如下: 
    1.支持客户/服务器模式。 
    2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。 
    由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。 
    3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。 
    4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。 
    5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

    二、使用方法

    使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

    首先需要导入HttpClientjar包,具体可以到官网下载,下载地址: http://hc.apache.org/downloads.cgi

    commons-codec-1.7.jar,commons-logging-1.1.1.jar,httpclient-4.2.2.jar,httpcore-4.2.2.jar

    1. 创建HttpClient对象,最新版的httpClient使用实现类的是closeableHTTPClient,以前的default作废了。

    2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

    3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

    4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

    5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

    6. 释放连接。无论执行方法是否成功,都必须释放连接

    三、使用实例

    3.1.HttpClient提交表单模拟用户登录

     1 package service;
     2 import java.io.IOException;
     3 import java.io.UnsupportedEncodingException;
     4 import java.util.ArrayList;
     5 import java.util.List;
     6 import org.apache.http.HttpEntity;
     7 import org.apache.http.NameValuePair;
     8 import org.apache.http.client.ClientProtocolException;
     9 import org.apache.http.client.entity.UrlEncodedFormEntity;
    10 import org.apache.http.client.methods.CloseableHttpResponse;
    11 import org.apache.http.client.methods.HttpPost;
    12 import org.apache.http.impl.client.CloseableHttpClient;
    13 import org.apache.http.impl.client.HttpClients;
    14 import org.apache.http.message.BasicNameValuePair;
    15 import org.apache.http.util.EntityUtils;
    16 
    17 public class ServiceHttpImpl implements ServiceHttp {
    18     /**
    19      * post方式提交表单,模拟用户登录请求
    20      */
    21     public void Login(String username, String password) {
    22         //1.创建默认的httpclient实例
    23         CloseableHttpClient httpclient = HttpClients.createDefault();
    24         String url = "http://localhost:8080/httpcillent/HttpCilentTest1?username="
    25                 + username + "&password=" + password;
    26         //2.创建httpPost
    27         HttpPost httpPost = new HttpPost(url);
    28         //3.创建参数队列
    29         List<NameValuePair> list = new ArrayList<NameValuePair>();
    30         list.add(new BasicNameValuePair("username", username));
    31         list.add(new BasicNameValuePair("password", password));
    32         /**
    33          * UrlEncodedFormEntity这个类是用来把输入数据编码成合适的内容  
    34          *两个键值对,被UrlEncodedFormEntity实例编码后变为如下内容:
    35          * key1=value1&key2=value2的形式
    36          */
    37         UrlEncodedFormEntity entity;
    38         CloseableHttpResponse response=null;
    39         try {
    40             entity=new UrlEncodedFormEntity(list,"utf-8");
    41             httpPost.setEntity(entity);//带上参数执行
    42             System.out.println("执行请求:"+httpPost.getURI());
    43             try {
    44                 response=httpclient.execute(httpPost);//响应结果 
    45                 HttpEntity httpEntity=response.getEntity();
    46                 if(httpEntity!=null){
    47                     System.out.println("-----------------");
    48                     System.out.println(EntityUtils.toString(httpEntity));
    49                     System.out.println("-----------------");
    50                 }
    51             } catch (ClientProtocolException e) {
    52                 e.printStackTrace();
    53             } catch (IOException e) {
    54                 e.printStackTrace();
    55             }
    56         } catch (UnsupportedEncodingException e) {
    57             e.printStackTrace();
    58         }finally{
    59             ServiceHttpImpl.CloseableHttpClient(httpclient);
    60             ServiceHttpImpl.CloseableHttpResponse(response);
    61         }
    62     }
    63     
    64     private static void CloseableHttpResponse(CloseableHttpResponse httpResponse) {
    65         if (httpResponse != null) {
    66             try {
    67                 httpResponse.close();
    68             } catch (IOException e) {
    69                 e.printStackTrace();
    70             }
    71         }
    72     }
    73 
    74     private static void CloseableHttpClient(CloseableHttpClient client) {
    75         if (client != null) {
    76             try {
    77                 client.close();
    78             } catch (IOException e) {
    79                 e.printStackTrace();
    80             }
    81         }
    82     }
    84     
    85 }
    4.2 HTTP实体的使用

    因为一个实体既可以代表二进制内容又可以代表字符内容,它也支持字符编码(支持后者也就是字符内容)。实体是当使用封闭内容执行请求,或当请求已经成功执行,或当响应体结果发功到客户端时创建的。

    要从实体中读取内容,可以通过HttpEntity#getContent()方法从输入流中获取,这会返回一个java.io.InputStream对象,或者提供一个输出流到HttpEntity#writeTo(OutputStream)方法中,这会一次返回所有写入到给定流中的内容。

    当实体通过一个收到的报文获取时,HttpEntity#getContentType()方法和HttpEntity#getContentLength()方法可以用来读取通用的元数据,如Content-Type和Content-Length头部信息(如果它们是可用的)。因为头部信息Content-Type可以包含对文本MIME类型的字符编码,比如text/plain或text/html,HttpEntity#getContentEncoding()方法用来读取这个信息。如果头部信息不可用,那么就返回长度-1,而对于内容类型返回NULL。如果头部信息Content-Type是可用的,那么就会返回一个Header对象。当为一个传出报文创建实体时,这个元数据不得不通过实体创建器来提供。

    4.3发送post请求

    public void testPost() {  
            // 创建默认的httpClient实例.    
            CloseableHttpClient httpclient = HttpClients.createDefault();  
            // 创建httppost    
            HttpPost httppost = new HttpPost("http://localhost:8080/");  
            // 创建参数队列    
            List<NameValuePair> list = new ArrayList<NameValuePair>();  
            list.add(new BasicNameValuePair("admin", "我心自在"));  
            UrlEncodedFormEntity uefEntity;  
            try {  
                uefEntity = new UrlEncodedFormEntity(list, "UTF-8");  
                httppost.setEntity(uefEntity);  
                System.out.println("executing request " + httppost.getURI());  
                CloseableHttpResponse response = httpclient.execute(httppost);  
                try {  
                    HttpEntity entity = response.getEntity();  
                    if (entity != null) {  
                        System.out.println("--------------------------------------");  
                        System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8"));  
                        System.out.println("--------------------------------------");  
                    }  
                } finally {  
                    response.close();  
                }  
            } catch (ClientProtocolException e) {  
                e.printStackTrace();  
            } catch (UnsupportedEncodingException e1) {  
                e1.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            } finally {  
                // 关闭连接,释放资源    
                try {  
                    httpclient.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  

    测试结果如下:

    4.3发送get请求

     public void testGet() {  
            CloseableHttpClient httpclient = HttpClients.createDefault();  
            try {  
                // 创建httpget.    
                HttpGet httpget = new HttpGet("http://www.baidu.com/");  
                System.out.println("executing request " + httpget.getURI());  
                // 执行get请求.    
                CloseableHttpResponse response = httpclient.execute(httpget);  
                try {  
                    // 获取响应实体    
                    HttpEntity entity = response.getEntity();  
                    System.out.println("--------------------------------------");  
                    // 打印响应状态    
                    System.out.println(response.getStatusLine());  
                    if (entity != null) {  
                        // 打印响应内容长度    
                        System.out.println("Response content length: " + entity.getContentLength());  
                        // 打印响应内容    
                        System.out.println("Response content: " + EntityUtils.toString(entity));  
                    }  
                    System.out.println("------------------------------------");  
                } finally {  
                    response.close();  
                }  
            } catch (ClientProtocolException e) {  
                e.printStackTrace();  
            } catch (ParseException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            } finally {  
                // 关闭连接,释放资源    
                try {  
                    httpclient.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        } 

     测试结果如下:

    总结httpGet和httpPost的区别和联系:

           HttpClient常用HttpGet和HttpPost这两个类,分别对应Get方式和Post方式。

           HttpPost方法提交HTTP POST请求,需要使用HttpPost类的setEntity方法设置请求参数。参数则必须用NameValuePair[]数组存储。

           get方式:以URL字串本身传递数据参数,在服务器端可以从'QUERY_STRING'这个变量中直接读取,效率较高,但缺乏安全性,也无法来处理复杂的数据。
           post方式:就传输方式讲参数会被打包在数据包中传输,从CONTENT_LENGTH这个环境变量中读取,便于传送较大一些的数据,同时因为不暴露数据在浏览器的地址栏中,安全性相对较高,但这样的处理效率会受到影响。

     表单提交中的post和get方法的区别:

    1.get是从服务器上查询/获取数据,post是向服务器传输数据。

    2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。

    3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。

    4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。

    5. get安全性非常低,传输数据可见,post安全性较高,传输数据不可见,但通过抓包工具post传递中的参数也可以看到,所以理论上也不是安全的。

    6. get是Form的默认方法。

  • 相关阅读:
    吴军博士《浪潮之巅》
    第十二周
    第十一周
    第十周
    第九周
    第四次作业
    第四周
    学习进度表
    世界是数字的
    第二阶段团队第八天成果。
  • 原文地址:https://www.cnblogs.com/10158wsj/p/6767209.html
Copyright © 2020-2023  润新知