HttpClient学习笔记

HttpClient Scope

基于Http的HTTP客户端传输库;基于经典的阻塞IO;内容不可知的。

HttpClient 不是一个浏览器,它是一个HTTP传输库,目的是传输和接收HTTP消息,不尝试处理HTTP内容,执行嵌入其中的JavaScript代码,尝试猜测内容类型。

 

基础

请求执行,客户端HttpClient,是线程安全的,单例的,应该只有一个。

HTTP请求,包装了HTTP协议的方法,HttpGet, HttpHead, HttpPost,HttpPut, HttpDelete, HttpTrace, and HttpOptions. 或者使用URIBuilder 构建请求。

HttpGet httpget = new HttpGet(
    "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");
   
    URI uri = new URIBuilder()
      .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);

HTTP响应,使用构建BasicHttpResponse响应,HttpResponse接收。

处理请求头,检索,增加,删除,使用HttpResponse方法,请求头封装类Header。或者从响应获取HeaderIterator接口,用迭代器的方式遍历请求头。解析请求头里面的单个元素,用HeaderIterator实例生成BasicHeaderElementIterator对象,可以解析请求头中的每个元素。

String url = null;
  url="https://www.cnblogs.com";
  CloseableHttpClient httpClient = HttpClients.createDefault();

  HttpGet httpGet = new HttpGet(url);
  CloseableHttpResponse response = null;
  try {
    response=httpClient.execute(httpGet);
      System.out.println(response.getProtocolVersion());
      System.out.println(response.getStatusLine());

      System.out.println("遍历请求头:");

      HeaderIterator iterator= response.headerIterator();
      while (iterator.hasNext()){
          System.out.println(iterator.next().toString());
      }

      System.out.println("遍历单个请求头的参数,使用response.headerIterator(\"Strict-Transport-Security\")");
      HeaderElementIterator it=new BasicHeaderElementIterator(response.headerIterator("Strict-Transport-Security"));

        while (it.hasNext()){
            HeaderElement headerElement=it.nextElement();
            System.out.println("element&:"+headerElement.getName()+",value&:"+headerElement.getValue());
            NameValuePair[] pairs=headerElement.getParameters();

            for (NameValuePair nameValuePair:pairs){
                System.out.println("param: "+nameValuePair);
            }
        }

  }catch (Exception exception){
      exception.printStackTrace();
  }
  finally {
      response.close();
  }
}

 

HTTP entity 请求实例,有三种类型,streamed不可重复读;self-contained在内存中的,可以重复读;wrapping包装,使用用一个实例,生成新的实例,包装模式。

 

public static void main(String[] args) throws IOException {
  String url = null;
  url="https://www.xsbiquge.com/20_20331/1421819.html";
  CloseableHttpClient httpClient = HttpClients.createDefault();

  HttpGet httpGet = new HttpGet(url);
  CloseableHttpResponse response = null;
  try {
      response=httpClient.execute(httpGet);
      HttpEntity httpEntity=response.getEntity();
      if(httpEntity!=null){
          InputStream inputStream=httpEntity.getContent();
          try{
              Scanner scanner=new Scanner(inputStream);
              Path paths=Paths.get("G:\\test.txt");
              //File file=new File(String.valueOf(paths));
              while(scanner.hasNext()) {
                  byte[] bytes = scanner.next().getBytes();
                  Files.write(paths, bytes, StandardOpenOption.APPEND);
              }

          }finally {
              inputStream.close();
          }
      }

  }catch (Exception exception){
      exception.printStackTrace();
  }
  finally {
      response.close();
  }
}

可重复读的,ByteArrayEntityorStringEntity。

使用实例中的信息 HttpEntity#getContentType() and HttpEntity#getContentLength() HttpEntity#getContentEncoding(),辅助类EntityUtils。

 

释放资源,包括释放从实例获取的输入流HttpEntity#getContent,关闭输入流,响应。

HttpEntity#writeTo(OutputStream)确保释放系统资源

 

EntityUtils#consume(HttpEntity)方法会确保实例内容被完全读取,而且底层输入流关闭。

 

消费实例的内容,为了重复读取实例的内容,使用BufferedHttpEntity实例,包装HttpEntity。

 

生产实例内容:在HTTP中只有PUT,POST方法能生产实例内容,使用StringEntity,ByteArrayEntity,InputStreamEntity, andFileEntity对象生产实例,使用httppost.setEntity(entity) 方法设置实例。

 

填写HTML表单,使用UrlEncodedFormEntity,MultipartEntity促进这个流程。

传统表单有两种形式:一种是普通登录形式;一种是上传文件形式。

登录模式,会有一个特殊的请求头,Content-Type: application/x-www-form-urlencoded; charset=UTF-8 。

上传文件形式,特殊的请求头是,multipart/form-data。

 

(1) 
使用最多的是UrlEncodedFormEntity类。通过该类创建的对象可以模拟传统的HTML表单传送POST请求中的参数。如下面的表单:

1.<form action="http://localhost/index.html" method="POST">
2.   <input type="text" name="param1" value="中国"/>
3.   <input type="text" name="param2" value="value2"/>
4.   <inupt type="submit" value="submit"/>
5.</form>
我们可以用下面的代码实现:

1.List<NAMEVALUEPAIR> formParams = new ArrayList<NAMEVALUEPAIR>();
2.formParams.add(new BasicNameValuePair("param1", "中国"));
3.formParams.add(new BasicNameValuePair("param2", "value2"));
4.HttpEntity entity = new UrlEncodedFormEntity(formParams, "UTF-8");
5.  
6.HttpPost request = new HttpPost(“http://localhost/index.html”);
7.request.setEntity(entity);
当然,如果想查看HTTP数据格式,可以通过HttpEntity对象的各种方法取得。如:

01.List<NAMEVALUEPAIR> formParams = new ArrayList<NAMEVALUEPAIR>();
02.formParams.add(new BasicNameValuePair("param1", "中国"));
03.formParams.add(new BasicNameValuePair("param2", "value2"));
04.UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, "UTF-8");
05.  
06.System.out.println(entity.getContentType());
07.System.out.println(entity.getContentLength());
08.System.out.println(EntityUtils.getContentCharSet(entity));
09.System.out.println(EntityUtils.toString(entity));
上例的打印结果如下:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
39
UTF-8
param1=中国&param2=value2
(2)
除了传统的application/x-www-form-urlencoded表单,我们另一个经常用到的是上传文件用的表单,这种表单的类型为multipart/form-data。在HttpClient程序扩展包(HttpMime)中专门有一个类与之对应,那就是MultipartEntity类。此类同样实现了HttpEntity接口。如下面的表单:

1.<form action="http://localhost/index.html" method="POST"
2.       enctype="multipart/form-data">
3.   <input type="text" name="param1" value="中国"/>
4.   <input type="text" name="param2" value="value2"/>
5.   <input type="file" name="param3"/>
6.   <inupt type="submit" value="submit"/>
7.</form>
我们可以用下面的代码实现:

1.MultipartEntity entity = new MultipartEntity();
2.entity.addPart("param1", new StringBody("中国", Charset.forName("UTF-8")));
3.entity.addPart("param2", new StringBody("value2", Charset.forName("UTF-8")));
4.entity.addPart("param3", new FileBody(new File("C:\\1.txt")));
5.  
6.HttpPost request = new HttpPost(“http://localhost/index.html”);
7.request.setEntity(entity);

 

 

合适的内容编码,使用entity.setChunked(true)。

 

响应处理handler, ResponseHandler接口,可以处理客户端传输回来的Http响应体,并返回json数据,使用辅助类Gson。

 

HttpClient 接口,有许多的HTTP设计,比如验证,连接策略都提供了一个门面接口,有其他的类实现。比如连接策略,DefaultConnectionKeepAliveStrategy实例。

 

HttpContext请求上下文,使用请求上下文,每个请求都可以使用请求上下文的属性发起连接,它不是线程安全的。

请求上下文的属性,HttpConnection,HttpHost,HttpRoute,HttpRequest,HttpResponse,RequestConfig,java.util.List<URI>

使用HttpClientContext.adapt(context) 简化与请求上下文的交互。

 

HTTP 协议拦截器,HttpRequestInterceptor,处理请求头,在发起请求前。

 

异常类HttpException ,默认请求下,会尝试从IO异常下自动恢复。

HttpClient能自动地修复某些异常,比如幂等性的方法,如果请求未到达服务器,那么客户端会自动尝试传输到服务器。

 

启动自定义异常恢复机制,使用HttpRequestRetryHandler接口。

 

终止请求,使用HttpUriRequest#abort(),这时线程安全的。

 

重定向处理策略,LaxRedirectStrategy实例。

 

 

路由:HttpClient能够直接或通过一个可能涉及多个中间连接的路由建立到目标主机的连接。HttpClient将路由的连接区分非 plain普通的,tunneled隧道的,layered分层的。

HttpClient的路由RouteInfo接口能获取路由信息,HttpRoute是一个实现类,HttpTracker是一个多线程实现类,HttpRouteDirector是一个帮助类。

HttpRoutePlanner是一个接口,表示基于执行上下文计算到给定目标的完整路由的政策。SystemDefaultRoutePlanner,DefaultProxyRoutePlanner是其实现类。

 

 

HTTP连接管理connection managers

目的是:重用连接

BasicHttpClientConnectionManager,PoolingHttpClientConnectionManager,默认下为每个路由创建2个并发连接,总共不超过20个连接。

 

 

连接拒绝策略,如果一个连接在服务端关闭,那么这个连接就不会有效,所以必须要想办法解决连接失效问题。

HttpClient的方法是启动一个线程检测连接是否有效,如果没有效,则关闭连接。

ClientConnectionManager#closeExpiredConnections()关闭过期的连接并从连接池中驱逐过期连接。

ClientConnectionManager#closeIdleConnections() 关闭在给定时间内的全部空闲连接。

 

连接活跃策略,服务端一般会在Keep-Alive请求头,指定一个长连接的时间,如果响应里面没有,那么客户端需要定值一个策略,不然服务端会关闭连接节约系统资源,并且不会告知客户端。

ConnectionKeepAliveStrategy实例。

 

HttpClient代理设置,它支持简单的直跳或者单跳,最简单的方法就是就是设置默认的代理参数。

HttpHost proxy = new HttpHost("someproxy", 8080);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CloseableHttpClient httpclient = HttpClients.custom()
      .setRoutePlanner(routePlanner)
      .build();

实现RoutePlanner接口,或者使用实现类DefaultProxyRoutePlanner,SystemDefaultRoutePlanner。

 

 

HTTP状态管理

HTTP Cookie管理,生成一个简单的cookie,使用BasicClientCookie对象,cookie可以设置它在那个domain,path下才有效。

 

cookie的规范,cookie有很多规范,如果需要可以指定cookie的规范,CookieSpecs这个类是一个枚举类。

 

cookie持久化,为了防止cookie丢失,可以使用cookiestore, 一个简单的BasicCookieStore对象,可以存储cookie,底层用arrraylist实现,cookiestore要与httpClient绑定。

 

HTTP的请求上下文也可以指定cookie规范和cookie持久化。

 

 

HTTP验证

用户验证,最简单的用户凭证是一个用户密码价值对,一个实例是UsernamePasswordCredentials。

NTCredentials是微软系统指定用户凭证。

 

Credentials providers证书提供者,维护一组用户凭证,并能够为特定的身份验证范围生成用户凭据。身份验证范围由主机名,端口号,领域名和身份验证方案名组成。

CredentialsProvider接口,默认的实现类是BasicCredentialsProvider。

CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
  new AuthScope("somehost", AuthScope.ANY_PORT),
  new UsernamePasswordCredentials("u1", "p1"));
credsProvider.setCredentials(
  new AuthScope("somehost", 8080),
  new UsernamePasswordCredentials("u2", "p2"));
credsProvider.setCredentials(
  new AuthScope("otherhost", 8080, AuthScope.ANY_REALM, "ntlm"),
  new UsernamePasswordCredentials("u3", "p3"));

 

HTTP验证和执行上下文

HttpClien依赖AuthState类来跟踪有关身份验证过程状态的详细信息。

HttpClientContext对象可以与CredentialsProvider接口,验证模式,验证缓存绑定。

 

 

 

posted @ 2020-10-17 19:55  lfcom  阅读(216)  评论(0编辑  收藏  举报