JAVA实现HTTP请求 之 HTTPClient

2年前 (2022) 程序员胖胖胖虎阿
219 0 0

一、目前JAVA实现HTTP请求的方法用的最多的有两种:
通过HTTPClient这种第三方开源框架去实现。HTTPClient对HTTP的封装性比较不错,基本上能够满足我们大部分的需求,最新的HttpClient4.5是org.apache.http.impl.client下操作远程 url的工具包;HttpClient3.1 是 org.apache.commons.httpclient下操作远程 url的工具包,虽然已不再更新,但实现工作中使用httpClient3.1的代码还是有不少的.
另一种则是通过HttpURLConnection去实现,HttpURLConnection是JAVA的标准类,是JAVA比较原生的一种实现方式。不要用这个了,有现成的工具为什么不用呢.

二、依赖

使用httpclient之前,先引入maven依赖:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.9</version>
</dependency>

三、HttpClient 之 URIBuilder 
构造函数
URIBuilder()
URIBuilder(final String string) 内部会创建URI对象: digestURI(new URI(string))
URIBuilder(final URI uri)
非空的两个构造实际内部都调用了digestURI(uri) 将URI对象解析并赋值给类的属性.

URIBuilder类中方法:
① get相关方法
 

    String url = "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=";
    URIBuilder uriBuilder = new URIBuilder(url);
    System.out.println(uriBuilder.getScheme());
    System.out.println(uriBuilder.getUserInfo());
    System.out.println(uriBuilder.getHost());
    System.out.println(uriBuilder.getPort());
    System.out.println(uriBuilder.getPath());
    System.out.println(uriBuilder.getQueryParams());
    System.out.println(uriBuilder.getFragment());
    System.out.println(uriBuilder.getCharset());
 
    输出如下所示:
    scheme:http
    userinfo:null
    host:www.google.com
    port:-1  端口默认是80,当显示指定端口时,此处便能取到值
    path:/search
    queryParams:[hl=en, q=httpclient, btnG=Google Search, aq=f, oq=]
    fragment:null
    charset:null
    
    某些属性含义未知手动设置一次
    String url = "http://info.sporttery.cn/football/info/fb_match_hhad.php?m=102909";
    URIBuilder uriBuilder = new URIBuilder(url);
    uriBuilder.setFragment("111");
    uriBuilder.setUserInfo("222", "333");
    uriBuilder.setCharset(new GBK());
    System.out.println(uriBuilder.build());
    System.out.println(uriBuilder.getScheme());
    System.out.println(uriBuilder.getUserInfo());
    System.out.println(uriBuilder.getHost());
    System.out.println(uriBuilder.getPath());
    System.out.println(uriBuilder.getQueryParams());
    System.out.println(uriBuilder.getFragment());
    System.out.println(uriBuilder.getCharset());
    输出如下:
    http://222:333@info.sporttery.cn/football/info/fb_match_hhad.php?m=102909#111
    scheme:http
    userInfo:222:333   没见过这东西-。-
    host:info.sporttery.cn
    path:/football/info/fb_match_hhad.php
    queryParams:[m=102909]
    fragment:111   路由
    charset:GBK

② 添加URI query参数方法

常用方法

setParameters(final List nvps)
setParameters(final NameValuePair… nvps)
addParameters(final List nvps)
上面的方法我觉得俩set其实是一样的, set会覆盖原来的同名参数而add不会

这里的NameValuePair :

只有一个实现类BasicNameValuePair就是用来设置参数键值对BasicNameValuePair(final String name, final String value)

String url = "http://ads-mediation.internal.zkq.sg/media/app?m=102909";
    
URIBuilder uriBuilder = new URIBuilder(url);
ArrayList<NameValuePair> objects = new ArrayList<>();
NameValuePair m = new BasicNameValuePair("m", "1");
objects.add(m);
ArrayList<NameValuePair> objects1 = new ArrayList<>();
NameValuePair m1 = new BasicNameValuePair("m", "8");
objects1.add(m1);
 
uriBuilder.setParameters(objects);
uriBuilder.addParameters(objects1);
System.out.println(uriBuilder.build());
输出:http://ads-mediation.internal.zkq.sg/media/app?m=1&m=8
 
得出结论:set会覆盖原来的同名参数而add不会

addParameter(final String param, final String value)
setParameter(final String param, final String value)
param和value会在这俩个方法内部组装成BasicNameValuePair. 
 

String url = "hhttp://ads-mediation.internal.zkq.sg/media/app?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.setParameter("m", "2");
uriBuilder.addParameter("m" ,"5");
System.out.println(uriBuilder.build());
输出:http://ads-mediation.internal.zkq.sg/media/app?m=2&m=5
    
得出结论:set会覆盖原来的同名参数而add不会

③ Clears URI query parameters.

  • clearParameters()  清除所有参数 (即?后的键值对)
String url = "http://ads-mediation.internal.zkq.sg/media/app?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.clearParameters();
System.out.println(uriBuilder.build());
输出:http://ads-mediation.internal.zkq.sg/media/app

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

1. 创建HttpClient对象。

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. 释放连接。无论执行方法是否成功,都必须释放连接

五、HttpClient之基本get用法

public class HttpClientDemo {
   public void getRequest(String url) throws URISyntaxException, IOException {
     //创建httpClient实例
     CloseableHttpClient client = HttpClients.createDefault();
     //创建一个uri对象
     URIBuilder uriBuilder = new URIBuilder(url);
     //塞入form参数
     uriBuilder.addParameter("account", "123");
     uriBuilder.addParameter("password", "123");
     //创建httpGet远程连接实例,这里传入目标的网络地址
     HttpGet httpGet = new HttpGet(uriBuilder.build());
     // 设置请求头信息,鉴权(没有可忽略)
     httpGet.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
     // 设置配置请求参数(没有可忽略)
     RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 连接主机服务超时时间
           .setConnectionRequestTimeout(35000)// 请求超时时间
           .setSocketTimeout(60000)// 数据读取超时时间
           .build();
     // 为httpGet实例设置配置
     httpGet.setConfig(requestConfig);
     //执行请求
     CloseableHttpResponse response = client.execute(httpGet);
     //获取Response状态码
      int statusCode = response.getStatusLine().getStatusCode();
      System.out.println(statusCode);
     //获取响应实体, 响应内容
      HttpEntity entity = response.getEntity();
     //通过EntityUtils中的toString方法将结果转换为字符串
      String str = EntityUtils.toString(entity);
      System.out.println(str);
      response.close();
      client.close();
   }
}
(如果用try catch 记得关闭资源)

六、HttpClient之post - json用法

 public String postRequest(String url, Map<String, Object> paramMap) {
     HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
     // 创建httpPost远程连接实例
     HttpPost post = new HttpPost(url);
     String result = "";
     try (CloseableHttpClient closeableHttpClient = httpClientBuilder.build()) {
        // HttpEntity entity = new StringEntity(jsonDataStr);
        // 修复 POST json 导致中文乱码
        HttpEntity entity = new StringEntity(paramMap.toString(), "UTF-8");
        post.setEntity(entity);
        post.setHeader("Content-type", "application/json");
        HttpResponse resp = closeableHttpClient.execute(post);
        try {
           InputStream respIs = resp.getEntity().getContent();
           byte[] respBytes = IOUtils.toByteArray(respIs);
           result = new String(respBytes, Charset.forName("UTF-8"));
        } catch (Exception e) {
           e.printStackTrace();
        }
        return result;
     } catch (IOException e) {
         e.printStackTrace();
     }
     return result;
}

七、HttpClient之post - form用法
form的关键在于生成NameValuePair ,这个集合里面放入form 表单的元素. 

随后使用 HttpPost 的 setEntity(new UrlEncodedFormEntity(nameValuePair, HTTP.UTF_8)) 方法塞入生成的form元素集合.

总得来说, 就是通过一个NameValuePair集合来存放待提交的参数,并将这个参数集合传入到一个UrlEncodedFormEntity中,然后调用HttpPost的setEntity()方法将构建好的UrlEncodedFormEntity传入. 代码如下:

List<NameValuePair>params=newArrayList<NameValuePair>();

Params.add(new BasicNameValuePair(“username”,”admin”));

Params.add(new BasicNameValuePair(“password”,”123456”));

UrlEncodedFormEntity entity=newUrlEncodedFormEntity(params,”utf-8”);

httpPost.setEntity(entity);
 

public static String postformRequest(String url, Map<String, Object> paramMap) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        String result = "";
        // 创建httpClient实例
        httpClient = HttpClients.createDefault();
        // 创建httpPost远程连接实例
        HttpPost httpPost = new HttpPost(url);
        // 配置请求参数实例(不需要可忽略)
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 设置连接主机服务超时时间
                .setConnectionRequestTimeout(35000)// 设置连接请求超时时间
                .setSocketTimeout(60000)// 设置读取数据连接超时时间
                .build();
        // 为httpPost实例设置配置(不需要可忽略)
        httpPost.setConfig(requestConfig);
        // 设置请求头
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
        // 封装表单参数
        if (null != paramMap && paramMap.size() > 0) {
            // 以下代码使用实现类BasicNameValuePair生成NameValuePair
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            // 通过map集成entrySet方法获取entity
            Set<Entry<String, Object>> entrySet = paramMap.entrySet();
            // 循环遍历,获取迭代器
            Iterator<Entry<String, Object>> iterator = entrySet.iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> mapEntry = iterator.next();
                nvps.add(new BasicNameValuePair(mapEntry.getKey(), mapEntry.getValue().toString()));
            }
 
            // 为httpPost设置封装好的请求参数
            try {
                // post实例塞参数的方法
                httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        try {
            // 服务器返回的所有信息都在HttpResponse中, httpClient对象执行post请求,并返回响应参数对象
            httpResponse = httpClient.execute(httpPost);
            // 先取出服务器返回的状态码,如果等于200说明success
            int code =httpResponse.getStatusLine().getStatusCode();
            // 从响应对象中获取响应内容
            // EntityUtils.toString()有重载方法
            // 这个静态方法将HttpEntity转换成字符串,防止服务器返回的数据带有中文,所以在转换的时候将字符集指定成utf-8即可
            HttpEntity entity = httpResponse.getEntity();
            result = EntityUtils.toString(entity,"UTF-8");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != httpResponse) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}
版权声明:程序员胖胖胖虎阿 发表于 2022年9月7日 上午5:40。
转载请注明:JAVA实现HTTP请求 之 HTTPClient | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...