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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • flutter自定义弹窗_app加弹窗

    flutter自定义弹窗_app加弹窗一.Fluttertoast库配置,可参考fluttertoast配置引用1.在pubspec.yaml中配置fluttertoast库,通过Pubget获取fluttertoast的版本,通过Pubupgrade更新,eg:#ThefollowingaddstheCupertinoIconsfonttoyourapplication.#UsewiththeCupertinoIconsclassforiOSstyleicons.cuper

    2022年9月24日
    0
  • shell 循环命令[通俗易懂]

    shell 循环命令[通俗易懂]1.for命令1.1for命令的使用bashshell提供了for命令,可以创建一个遍历一系列值的循环。每次一轮循环都使用其中一个值来执行已定义好的一组命令。下面是bashshell中for命令的基本格式。forvarinlistdocommandsdone还可以是这样的形式forvarinlist;do注意这里的list这不是shell的关键词,list只是想说明这是由数值,字符,字符串所组成的列表,for循环来遍历这

    2022年7月24日
    6
  • pycharm配置svn有什么用_SVN安装配置

    pycharm配置svn有什么用_SVN安装配置PyCharm是一款非常优秀的PythonIDE,以前用Editplus,用惯了感觉还行。用了PyCharm后被它丰富的功能吸引了。无论是普通python脚本、Django框架项目、还是GoogleAppEngine项目,它都能完美运行。不过设置起来比较麻烦,比如Subversion的用法我就一直没参透,我总是写完代码后出去用小乌龟提交。今天google一下,终于搞定了。现在写完代码后直接在…

    2022年8月26日
    2
  • 贝叶斯网络分析软件Netica

    贝叶斯网络分析软件Netica贝叶斯网络分析软件Netica使用方法软件介绍Netica软件是由NORSYSsoftwarecorp.出品,是目前世界上应用最广泛的贝叶斯网络分析软件,以简单、可靠、高效的目的开发软件。它是世界上著名的大公司、政府机构作为决策工具,广泛应用于商业、工程、医药和生态分析。软件界面软件打开界面如下,功能栏中很多功能键都是灰色的,此时不能用。左下角的Neticamessages会记录在Netica里面的操作过程。首先进行贝叶斯网络分析,需要构建网络network,方法有3种:File–New

    2022年6月21日
    39
  • NoSQL 数据库产品学习总结(一)「建议收藏」

    NoSQL 数据库产品学习总结(一)

    2022年2月3日
    53
  • java的class文件_java class是什么意思

    java的class文件_java class是什么意思根据 Java 虚拟机规范,类文件由单个 ClassFile 结构组成:ClassFile { u4 magic; //Class 文件的标志 u2 minor_version;//Class 的小版本号 u2 major_version;//Class 的大版本号 u2 constant_pool_count;//常量池的数量 cp_info consta

    2022年8月8日
    3

发表回复

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

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