Apache Client使用说明第一章(第二部分)

Apache Client使用说明第一章(第二部分)

1.2  HttpClient接口

HttpClient接口代表了HTTP请求执行最重要的约定.它规定了请求执行过程无任何和限制或者特定的细节以及审阅连接管理,状态管理,认证和重定向处理的实现等细节.这使得装饰接口附加功能更容易比如响应内容的缓存.

通常HttpClient的实现只是作为样子,大量特殊目的的处理器或策略接口的实现来处理HTTP协议具体的各个方面比如重定向或者认证的处理或者决定连接持续的时间.这使得用户可以替换某些默认的实现.

ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy(){
    public long getKeepAliveDuration(HttpResponse response, HttpContext context){
        long keepAlive = super.getKeepAliveDuration(response,context);
        if(keepAlive == -1) {
            //Keep connections alive 5 seconds if keep-alive value
            //has not be explicitly set by the server
            keepAlive = 5000;
        }
        return keepAlive;
    }
};

CloseableHttpClient httpclient = HttpClients.custom().setKeepAliveStrategy(keepAliveStrat).build();

1.2.1  HttpClient线程安全

HttpClient实现可以认为是线程安全的.推荐对于多次请求的执行使用该类的同一个实例.

1.2.2  

HttpClient资源的解除

当CloseableHttpClient实例不在使用且超出该示例相关的连接管理的作用域是必须通过调用CloseableHttpClient#close()方法关闭.

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

1.3  HTTP执行上下文

最初的HTTP被设计成无状态的,响应请求导向协议.然而真实环境中的应用经常需要通过多个逻辑上关联的请求响应交互保存状态信息.为了是程序能够保持处理状态HttpClient允许HTTP请求在特定的上下文中执行.当同一个上下文被一系列的请求复用,逻辑关联的请求将共享一个逻辑上的session.HTTP上下文功能类似于java.util.Map<String,Object>.一个简单的键值对集合.应用程序可以在执行时填充上下文或者在执行完成后检查上下文.

HttpContext可以包含任意的对象因此在多个线程共享是不保证线程安全.推荐每个线程位置自己的上下文.

在HTTP请求执行过程中HttpClient添加以下上下文属性:

HttpConnection 代表实际抵达目标服务器的连接.

HttpHost 代表连接的目标

HttpRoute 代表完整的连接路由

HttpRequest 代表实际的HTTP请求.最终的HttpRequest对像始终表示消息已被发送到目标服务器的状态.默认的HTTP/1.0和HTTP1.1使用相对请求URI.但是如果请求通过非隧道模式的代理发送则URI是绝对的.

HttpResponse 代表示例的HTTP响应

java.lang.Boolean 代表请求是否完全的传送到连接的目标.

RequestConfig 代表实际的请求设置.

java.util.List<URI> 代表在请求执行过程中接收到的所有重定向位置集合

可以使用HttpClientContext适配类来简化上下文之间的差异.

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

代表一个逻辑上相关的会话的请求序列应该用相同的HttpContext实例执行以确保上下文和状态信息在请求间的共享.

在接下来的示例中由初始请求配置将在执行上下文中保持并共享给其他相同上下文中的请求.

CloseableHttpClient httpclient = HttpClients.createDefault();
RequestConfig requestConfig = ReuestConfig.custom().setSocketTimeout(1000).setConnectTimeout(1000).build();
HttpGet httpget1 = new HttpGet();
httpget1.setConfig(requestConfig);
CloseableHttpResponse response1 = httpclient.execute(httpget1,context);
try {
    HttpEntity entity1 = response1.getEntity();
} finally {
    response1.close();
}

HttpGet httpget2 = new HttpGet();
httpget2.setConfig(requestConfig);
CloseableHttpResponse response1 = httpclient.execute(httpget2,context);
try {
    HttpEntity entity1 = response1.getEntity();
} finally {
    response1.close();
}

1.4  HTTP协议拦截器

HTTP请求拦截器是HTTP协议具体的常规实现.一般协议拦截预期作用在传入消息一个特定的头部或一组相关的头部.协议拦截器也可以操作消息封装的实体内容-传输内容的压缩和解压是最好的例子.这通常可以使用装饰器模式包装原有实体来完成.多个协议拦截器可以被组成一个逻辑单元.

协议拦截器可以通过共享信息合作-比如处理状态-通过HTTP执行上下文.协议拦截器可以存储一个或一系列请求的处理状态.通常这种拦截器的执行顺序并不重要,只要他们不依赖执行上下文的状态.如果协议拦截具有相互依赖关系而必须以特定顺序执行,则应保证添加的顺序与预期执行的顺序一致.

协议拦截器必须为线程安全的实现.与servlet类似,协议拦截器不应该使用实例变量除非对这些变量进行同步.

下面的例子展示上下文如何用于维持一系列请求的处理状态:

CloseableHttpClient httpclient = HttpClients.custom().addInterceptorLast(new HttpRequestInterceptor(){
    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException{
        AtomicInteger count = (AtomicInteger)context.getAttribute("count");
    }
}).build();

AtomicInteger count = new AtomicInteger(1);
HttpClientContext localContext = HttpClientContext.create();
localContext.setAttribute("count",count);

HttpGet httpget = new HttpGer("");
for(int i = 0; i < 10; i++){
    CloseableHttpResponse response = httpclient.execute(httpget, localContext);
    try{
        HttpEntity entity = response.getEntity();
    } finally {
        response.close();
    }
}

1.5  异常处理

HTTP协议的处理这可能抛出两种类型的异常:java.io.IOException 表示I/O失败比如套接字超时或套接字重置,HttpException表示HTTP失败比如违背了HTTP协议.通常I/O错误是非致命和可恢复,然而HTTP协议错误是致命的且无法自动恢复.请注意HttpClient的实现会重新用java.io.IOException的子类ClientProtocolException抛出HttpException.用户可以在同一个catch代码块中处理I/O错误和协议错误.

1.5.1  HTTP传输安全

HTTP协议并不适合所有类型的应用。HTTP 是一个面向简单的请求/响应协议,最初设计来支持静态或动态生成的内容检索。HTTP从未有意支持事务操作。比如,HTTP服务器将考虑其合同履行的一部分,如果它成功地接收和处理请求,生成一个响应并发送状态码至客户端。服务器不会试图回滚事务当客户端因读取超时、请求取消或系统故障而接收响应实体失败。如果客户端决定重试相同的请求,服务器最终将不可避免地多次执行相同的事务。在某些情况下,这可能会导致应用程序数据损坏或不一致的应用程序状态。

尽管HTTP从未被设计成支持事务处理,它仍然满足作为关键任务应用程序传输协议所需满足的条件。

1.5.2  幂等方法

1.5.3  异常自动恢复

默认的HttpClient试图自动从I/O异常中恢复.默认的自动恢复机制只能处理一小部分异常.

HttpClient不会尝试从任何逻辑或HTTP协议错误中恢复(继承自HttpException类).

HttpClient将自动重试被认定的幂等方法.

HttpClient将自动重试当HTTP请求仍然在传输到目标服务器失败的方法(比如请求还没有完全传输到服务器).

1.5.4  请求重试处理方法

HttpRequestRetryHandler接口的实现用于自定义异常回复机制.

HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler(){
    public boolean retryRequest(IOException exception, int executionCouont, HttpContext context){
        if(executionCount >= 5){
            return false;
        }
        if(exception instanceof InterruptedIOException){
            return false;
        }
        if(exception instanceof UnknownHostException){
            return false;
        }
        if(exception instanceof ConnecTimeoutException){
            return false;
        }
        if(exception instanceof SSLException){
            return false;
        }
        HttpClientContext clientContext = HttpClientContext.adapt(context);
        HttpRequest request = clientContext.getRequest();
        boolean idmpotent - !(request instanceof HttpEntityEnclosingRequest);
        if(idempotent){
            return true;
        }
        return false;
    }
};
CloseableHttpClient httpclient = HttpClients.custom().setRetryHandler(myRetryHandler).build();

请注意可以使用StandardHttpRequestRetryHandler替代默认配置以便RFC-2616定义的幂等方法可以安全的自动重试:GET,HEAD,PUT,DELTE,OPTIONS和TRACE.

1.6  终止请求

在某些情况下HTTP请求可能由于目标服务器高负荷或者客户端有太多的请求在使用导致请求在预期的时间范围内执行失败.在这种情况下可能有必要提前终止该请求并解除执行线程对I/O操作的阻塞.通过HttpClient执行的HTTP请求可以在执行的任何阶段调用HttpUriRequest#abort()方法终止.该方法是线程安全的可以从任何线程调用.当HTTP请求终止执行现场-即使当前阻塞的I/O操作-通过抛出InterruptedIOException保证解除.

1.7  重定向处理

HttpClient自动处理所有类型的重定向,除了那些HTTP规范要求必须用户介入.POST和PUT请求的see Other(状态code 303)重定向按HTTP规范的要求转换成GET请求.可以自定义重定向策略覆盖HTTP规范规定的方式.

LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();
CloseableHttpClient httpclient = HttpClients.custom().setRedirectStrategy(redirectStrategy).build();

HttpClient经常需要在执行过程中重写请求信息.默认的HTTP/1.0和HTTP/1.1通常使用相对请求URIS.同样,原始的请求也可能从其他位置重定向多次.最总的绝对HTTP位置可使用原始的请求和上下文获得.工具方法URIUtils#resolve可以用来解释绝对URI用于最终的请求.该方法包括重定向请求或原始请求的最后一个片段标识符.

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpClientContext context = HttpClientContext.create();
HttpGet httpget = new HttpGet();
CloseableHttpResponse response = httpclient.execute(httpget,context);
try{
    HttpPost target = context.getTargetHost();
    List<URI> redirectLocations = context.getRedirectLocations();
    URI location = URIUtils.resolve(httpget.getURI(),target,redirectLocations);
    System.out.println("Final HTTP location: " + location.toASCIIString());
} finally {
    response.close();
}

 

 

转载于:https://my.oschina.net/yaoliyc/blog/526475

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109259.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • databus教程_搭建区观察记录表

    databus教程_搭建区观察记录表最近公司因需要同步oracle数据到mysql,调研了Datax对于大数据量的同步代价有些大。开源的databus需要对源码做二次开发,才可以使用,前期我们搭建后,用自带的person表做了测试。确认可行后研发更改了源码。准备工作:1.配制gradle和java2.ojdbc6-11.2.0.2.0.jar放到如下目录:databus-master/sandbox-repo/com/oracle/ojdbc6/11.2.0.2.0/更改defaultEnvironment.gradl

    2022年8月31日
    0
  • java如何输入字符串?「建议收藏」

    java如何输入字符串?「建议收藏」关于java如何输入字符串的文章早已是非常多了,本文是对我个人过往学习java,理解及应用java字符串的一个总结。此文内容涉及java如何输入字符串等相关问题,希望对大家有所帮助。java如何输入字符串?首先,导入java.util.*包。然后,你需要新建一个读取标准输入(键盘)的扫描器对象。现在,你可以从键盘输入字符串了。以上这一行把键盘输入的一行字符串读取到变量s中。请看一个完整的简单示例:以上就是java如何输入字符串的详细内容。我整理了一些ja

    2022年7月16日
    7
  • npm 淘宝镜像

    npm 淘宝镜像

    2022年3月8日
    43
  • Unity3d场景快速烘焙【2020】

    Unity3d场景快速烘焙【2020】很多刚刚接触Unity3d的童鞋花了大量的时间自学,可总是把握不好Unity3d的烘焙,刚从一个坑里爬出来,又陷入另一个新的坑,每次烘焙一个场景少则几个小时,多则几十个小时,机器总是处于假死机状态,半天看不到结果,好不容易烘焙完了,黑斑、撕裂、硬边、漏光或漏阴影等缺陷遍布,惨不忍睹,整体效果暗无层次,或者苍白无力,灯光该亮的亮不起来,该暗的暗不下去,更谈不上有什么意境,痛苦的折磨,近乎失去了信心,一个团队从建模到程序,都没什么问题,可一到烘焙这一关,就堵得心塞,怎么也搞不出好的视觉效果,作品没法及时向用户交

    2022年6月11日
    27
  • httpd 启动报错“”Permission denied: make_sock: could not bind to address [::]:80“”

    httpd 启动报错“”Permission denied: make_sock: could not bind to address [::]:80“”

    2022年3月12日
    37
  • php建站错误代码0xc0000005,0xc0000005是什么错误-0xc0000005错误代码解决方法介绍-沧浪系统…

    php建站错误代码0xc0000005,0xc0000005是什么错误-0xc0000005错误代码解决方法介绍-沧浪系统…我们的电脑在进行各种各样的操作的时候有时会出现一些我们看不懂的报错,这种不知道错在哪了的问题让人很烦恼,下面就让小编来给大家介绍一下0xc0000005错误代码解决方法介绍吧。0xc0000005错误代码介绍0xc0000005这个错误一般是以显卡驱动模块相关,或者是第三方软件而引起的系统错误。解决方法一、如果是问题出在系统模块,那就需要厂商网站下载适用系统的最新驱动。二、如果是第三方软件引起的就…

    2022年9月1日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号