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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Android代码混淆及反编译

    Android代码混淆及反编译如果你目前还是一名学生或是没有在应用商店中上传过应用,恐怕对此的感受不深。而在企业中对Java代码的混淆却是一步很重要的步骤,从安全的角度来说,代码混淆,防止居心不良的人对代码进行恶意篡改非常重要。下面就是对Android项目进行的代码混淆和加密签名过程。

  • 卡巴斯基的离线更新以及病毒库备份[通俗易懂]

    卡巴斯基的离线更新以及病毒库备份[通俗易懂]卡巴斯基的离线更新以及病毒库备份 1、如果你用的是卡巴斯基5.0…..(….为版本号),病毒库在X:\DocumentsandSettings\AllUsers\ApplicationData\KasperskyAnti-VirusPersonal\5.0\base(其中X为安装时操作系统盘符,下同。专业版为X:\DocumentsandSettings\AllUsers…

  • qt中connect函数信号写法_qt中connect函数用法

    qt中connect函数信号写法_qt中connect函数用法*.cpp//带参数的拉姆达表达式connect(this,&Widget::mySignal,[=](intcount){qDebug()<<count;});mySignal(123456);*.hsignals:voidmySignal(intcount);注意:要在pro文件中加上CONFIG+=C++11…

  • Android系统五大布局详解Layout

    Android系统五大布局详解Layout我们知道Android系统应用程序一般是由多个Activity组成,而这些Activity以视图的形式展现在我们面前,视图都是由一个一个的组件构成的。组件就是我们常见的Button、TextEdit等等。那么我们平时看到的Android手机中那些漂亮的界面是怎么显示出来的呢?这就要用到Android的布局管理器了,网上有人比喻的很好:布局好比是建筑里的框架,组件按照布局的要求依次排列,就组成了用于

  • 零拷贝是什么_file.copy()

    零拷贝是什么_file.copy()一、DMAio读写有两种方式:中断 DMA用户进程发起数据读取请求 系统调度为该进程分配cpu cpu向io控制器(ide,scsi)发送io请求 用户进程等待io完成,让出cpu 系统调度cpu执行其他任务 数据写入至io控制器的缓冲寄存器 缓冲寄存器满了向cpu发出中断信号 cpu读取数据至内存通过中断,cpu需要拷贝数据。2、DMA用户进程发起…

  • 微博第三方登陆请求授权出现错误码:21322(重定向地址不匹配)的解决方法

    微博第三方登陆请求授权出现错误码:21322(重定向地址不匹配)的解决方法

    2021年10月25日

发表回复

您的电子邮箱地址不会被公开。

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