收藏 分享(赏)

client帮助文档.doc

上传人:精品资料 文档编号:10822222 上传时间:2020-01-12 格式:DOC 页数:13 大小:74.50KB
下载 相关 举报
client帮助文档.doc_第1页
第1页 / 共13页
client帮助文档.doc_第2页
第2页 / 共13页
client帮助文档.doc_第3页
第3页 / 共13页
client帮助文档.doc_第4页
第4页 / 共13页
client帮助文档.doc_第5页
第5页 / 共13页
点击查看更多>>
资源描述

1、前言超文本传输协议(HTTP)也许是当今互联网上使用的最重要的协议了。Web 服务,有网络功能的设备和网络计算的发展,都持续扩展了 HTTP 协议的角色,超越了用户使用的Web 浏览器范畴,同时,也增加了需要 HTTP 协议支持的应用程序的数量。尽管 包提供了基本通过 HTTP 访问资源的功能,但它没有提供全面的灵活性和其它很多应用程序需要的功能。HttpClient 就是寻求弥补这项空白的组件,通过提供一个有效的,保持更新的,功能丰富的软件包来实现客户端最新的 HTTP 标准和建议。为扩展而设计,同时为基本的 HTTP 协议提供强大的支持,HttpClient 组件也许就是构建HTTP 客

2、户端应用程序,比如 web 浏览器,web 服务端,利用或扩展 HTTP 协议进行分布式通信的系统的开发人员的关注点。1. HttpClient 的范围基于 HttpCorehttp:/hc.apache.org/httpcomponents-core/index.html的客户端 HTTP 运输实现库基于经典(阻塞)I/O内容无关2. 什么是 HttpClient 不能做的HttpClient 不是一个浏览器。它是一个客户端的 HTTP 通信实现库。HttpClient 的目标是发送和接收 HTTP 报文。HttpClient 不会去缓存内容,执行 嵌入在 HTML 页面中的 javascr

3、ipt代码,猜测内容类型,重新格式化请求/重定向 URI,或者其它和 HTTP 运输无关的功能。第一章 基础1.1 执行请求HttpClient 最重要的功能是执行 HTTP 方法。一个 HTTP 方法的执行包含一个或多个 HTTP请求/HTTP 响应交换,通常由 HttpClient 的内部来处理。而期 望用户提供一个要执行的请求对象,而 HttpClient 期望传输请求到目标服务器并返回对应的响应对象,或者当执行不成功时抛出异常。很自然地,HttpClient API 的主要切入点就是定义描述上述规约的 HttpClient 接口。这里有一个很简单的请求执行过程的示例:HttpClien

4、t httpclient = new DefaultHttpClient();HttpGet httpget = new HttpGet(“http:/localhost/“);HttpResponse response = httpclient.execute(httpget);HttpEntity entity = response.getEntity();if (entity != null) InputStream instream = entity.getContent();int l;byte tmp = new byte2048;while (l = instream.read(

5、tmp) != -1) 1.1.1 HTTP 请求所有 HTTP 请求有一个组合了方法名,请求 URI 和 HTTP 协议版本的请求行。HttpClient 支持所有定义在 HTTP/1.1版本中的 HTTP 方法:GET,HEAD,POST,PUT,DELETE ,TRACE 和 OPTIONS。对于每个方法类 型都有一个特殊的类:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace 和 HttpOptions。请求的 URI 是统一资源定位符,它标识了应用于哪个请求之上的资源。HTTP 请求 URI 包含一个协议模式,主机名称,可选的

6、端口,资源路径,可选的查询和可选的片段。HttpGet httpget = new HttpGet(“http:/ 提供很多工具方法来简化创建和修改执行 URI。URI 也可以编程来拼装:URI uri = URIUtils.createURI(“http“, ““, -1, “/search“,“q=httpclientHttpGet httpget = new HttpGet(uri);System.out.println(httpget.getURI();输出内容为:http:/ BasicNameValuePair(“q“, “httpclient“);qparams.add(new

7、BasicNameValuePair(“btnG“, “Google Search“);qparams.add(new BasicNameValuePair(“aq“, “f“);qparams.add(new BasicNameValuePair(“oq“, null);URI uri = URIUtils.createURI(“http“, ““, -1, “/search“,URLEncodedUtils.format(qparams, “UTF-8“), null);HttpGet httpget = new HttpGet(uri);System.out.println(httpge

8、t.getURI();输出内容为:http:/ 200 OK1.1.3 处理报文头部一个 HTTP 报文可以包含很多描述如内容长度,内容类型等信息属性的头部信息。HttpClient 提供获取,添加,移除和枚举头部信息的方法。HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, “OK“);response.addHeader(“Set-Cookie“,“c1=a; path=/; domain=localhost“);response.addHeader(“Set-Cookie

9、“,“c2=b; path=“/“, c3=c; domain=“localhost“);Header h1 = response.getFirstHeader(“Set-Cookie“);System.out.println(h1);Header h2 = response.getLastHeader(“Set-Cookie“);System.out.println(h2);Header hs = response.getHeaders(“Set-Cookie“);System.out.println(hs.length);输出内容为:Set-Cookie: c1=a; path=/; do

10、main=localhostSet-Cookie: c2=b; path=“/“, c3=c; domain=“localhost“获得给定类型的所有头部信息最有效的方式是使用 HeaderIterator 接口。HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, “OK“);response.addHeader(“Set-Cookie“,“c1=a; path=/; domain=localhost“);response.addHeader(“Set-Cookie“,“c2=

11、b; path=“/“, c3=c; domain=“localhost“);HeaderIterator it = response.headerIterator(“Set-Cookie“);while (it.hasNext() System.out.println(it.next();输出内容为:Set-Cookie: c1=a; path=/; domain=localhostSet-Cookie: c2=b; path=“/“, c3=c; domain=“localhost“它也提供解析 HTTP 报文到独立头部信息元素的方法方法。HttpResponse response = n

12、ew BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, “OK“);response.addHeader(“Set-Cookie“,“c1=a; path=/; domain=localhost“);response.addHeader(“Set-Cookie“,“c2=b; path=“/“, c3=c; domain=“localhost“);HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(“Set-Cookie

13、“);while (it.hasNext() HeaderElement elem = it.nextElement();System.out.println(elem.getName() + “ = “ + elem.getValue();NameValuePair params = elem.getParameters();for (int i = 0; i “);writer.write(“ “);writer.write(“ important stuff“);writer.write(“ “);writer.write(“);writer.flush();HttpEntity ent

14、ity = new EntityTemplate(cp);HttpPost httppost = new HttpPost(“http:/localhost/handler.do“);httppost.setEntity(entity);1.1.7.2 HTML 表单许多应用程序需要频繁模拟提交一个 HTML 表单的过程,比如,为了来记录一个 Web 应用程序或提交输出数据。HttpClient 提供了特殊的实体类 UrlEncodedFormEntity 来这个满足过程。List formparams = new ArrayList();formparams.add(new BasicNam

15、eValuePair(“param1“, “value1“);formparams.add(new BasicNameValuePair(“param2“, “value2“);UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, “UTF-8“);HttpPost httppost = new HttpPost(“http:/localhost/handler.do“);httppost.setEntity(entity);UrlEncodedFormEntity 实例将会使用 URL 编码来编码参数,生成如下的

16、内容:param1=value1 charset=“UTF-8“);entity.setChunked(true);HttpPost httppost = new HttpPost(“http:/localhost/acrtion.do“);httppost.setEntity(entity);1.1.8 响应控制器控制响应的最简便和最方便的方式是使用 ResponseHandler 接口。这个放完完全减轻了用户关于连接管理的担心。当使用 ResponseHandler 时,HttpClient 将会自动关注并保证释放连接到连接管理器中去,而不管请求执行是否成功或引发了异常。HttpClien

17、t httpclient = new DefaultHttpClient();HttpGet httpget = new HttpGet(“http:/localhost/“);ResponseHandler handler = new ResponseHandler() public byte handleResponse(HttpResponse response) throws ClientProtocolException, IOException HttpEntity entity = response.getEntity();if (entity != null) return E

18、ntityUtils.toByteArray(entity); else return null;byte response = httpclient.execute(httpget, handler);1.2 HTTP 执行的环境最 初, HTTP 是被设计成无状态的,面向请求- 响应的协议。然而,真实的应用程序经常需要通过一些逻辑相关的请求-响应交换来持久状态信息。为了开启应用程 序来维持一个过程状态,HttpClient 允许 HTTP 请求在一个特定的执行环境中来执行,简称为 HTTP 上下文。如果相同的环境在连续请求之间重用, 那么多种逻辑相关的请求可以参与到一个逻辑会话中。HTTP

19、 上下文功能和 java.util.Map很相似。 它仅仅是任意命名参数值的集合。应用程序可以在请求之前或在检查上下文执行完成之后来填充上下文属性。在 HTTP 请求执行的这一过程中,HttpClient 添加了下列属性到执行上下文中:http.connection:HttpConnection 实例代表了连接到目标服务器的真实连接。http.target_host:HttpHost 实例代表了连接目标。http.proxy_host:如果使用了,HttpHost 实例代表了代理连接。http.request:HttpRequest 实例代表了真实的 HTTP 请求。http.response

20、:HttpResponse 实例代表了真实的 HTTP 响应。http.request_sent:java.lang.Boolean 对象代表了暗示真实请求是否被完全传送到目标连接的标识。比如,为了决定最终的重定向目标,在请求执行之后,可以检查 http.target_host 属性的值:DefaultHttpClient httpclient = new DefaultHttpClient();HttpContext localContext = new BasicHttpContext();HttpGet httpget = new HttpGet(“http:/ response = h

21、ttpclient.execute(httpget, localContext);HttpHost target = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);System.out.println(“Final target: “ + target);HttpEntity entity = response.getEntity();if (entity != null) entity.consumeContent();输出内容为:Final target: http:/www.google.c

22、h1.3 异常处理HttpClient 能够抛出两种类型的异常:在 I/O 失败时,如套接字连接超时或被重置的java.io.IOException 异常,还有标志 HTTP 请求失败的信号,如 违反 HTTP 协议的HttpException 异常。通常 I/O 错误被认为是非致命的和可以恢复的,而 HTTP 协议错误则被认为是致命的而且是不能自动恢 复的。1.3.1 HTTP 运输安全要 理解 HTTP 协议并不是对所有类型的应用程序都适合的,这一点很重要。 HTTP 是一个简单的面向请求/响应的协议,最初被设计用来支持取回静态或动态生成 的内容。它从未向支持事务性操作方向发展。比如,如果

23、成功收到和处理请求,HTTP 服务器将会考虑它的其中一部分是否完成,生成一个响应并发送一个状态码 到客户端。如果客户端因为读取超时,请求取消或系统崩溃导致接收响应实体失败时,服务器不会试图回滚事务。如果客户端决定重新这个请求,那么服务器将不可 避免地不止一次执行这个相同的事务。在一些情况下,这会导致应用数据损坏或者不一致的应用程序状态。尽管 HTTP 从来都没有被设计来支持事务性处理,但它也能被用作于一个传输协议对关键的任务应用提供被满足的确定状态。要保证 HTTP 传输层的安全,系统必须保证 HTTP 方法在应用层的幂等性。1.3.2 幂等的方法HTTP/1.1 明确地定义了幂等的方法,描述

24、如下方法也可以有“幂等”属性在那些(除了错误或过期问题)N 的副作用0的相同请求和独立的请求是相同的换句话说,应用程序应该保证准备着来处理多个相同方法执行的实现。这是可以达到的,比如,通过提供一个独立的事务 ID 和其它避免执行相同逻辑操作的方法。请注意这个问题对于 HttpClient 是不具体的。基于应用的浏览器特别受和非幂等的 HTTP方法相关的相同问题的限制。HttpClient 假设没有实体包含方法,比如 GET 和 HEAD 是幂等的,而实体包含方法,比如POST 和 PUT 则不是。1.3.3 异常自动恢复默认情况下,HttpClient 会试图自动从 I/O 异常中恢复。默认的

25、自动恢复机制是受很少一部分已知的异常是安全的这个限制。HttpClient 不会从任意逻辑或 HTTP 协议错误(那些是从 HttpException 类中派生出的)中恢复的。HttpClient 将会自动重新执行那么假设是幂等的方法。HttpClient 将会自动重新执行那些由于运输异常失败,而 HTTP 请求仍然被传送到目标服务器(也就是请求没有完全被送到服务器)失败的方法。HttpClient 将会自动重新执行那些已经完全被送到服务器,但是服务器使用 HTTP 状态码(服务器仅仅丢掉连接而不会发回任何东西)响应时失败的方法。在这种情况下,假 设请求没有被服务器处理,而应用程序的状态也没有

26、改变。如果这个假设可能对于你应用程序的目标 Web 服务器来说不正确,那么就强烈建议提供一个自定义的异 常处理器。1.3.4 请求重试处理为了开启自定义异常恢复机制,应该提供一个 HttpRequestRetryHandler 接口的实现。DefaultHttpClient httpclient = new DefaultHttpClient();HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() public boolean retryRequest(IOException exception,int

27、executionCount,HttpContext context) if (executionCount = 5) / 如果超过最大重试次数,那么就不要继续了return false;if (exception instanceof NoHttpResponseException) / 如果服务器丢掉了连接,那么就重试return true;if (exception instanceof SSLHandshakeException) / 不要重试 SSL 握手异常return false;HttpRequest request = (HttpRequest) context.getAtt

28、ribute(ExecutionContext.HTTP_REQUEST);boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);if (idempotent) / 如果请求被认为是幂等的,那么就重试return true;return false;httpclient.setHttpRequestRetryHandler(myRetryHandler);1.4 中止请求在 一些情况下,由于目标服务器的高负载或客户端有很多活动的请求,那么 HTTP 请求执行会在预期的时间框内而失败。这时,就可能不得不过早地中

29、止请求,解除 封锁在 I/O 执行中的线程封锁。被 HttpClient 执行的 HTTP 请求可以在执行的任意阶段通过调用HttpUriRequest#abort()方 法而中止。这个方法是线程安全的,而且可以从任意线程中调用。当一个 HTTP 请求被中止时,它的执行线程就封锁在 I/O 操作中了,而且保证通过抛出 InterruptedIOException 异常来解锁。1.5 HTTP 协议拦截器HTTP 协议拦截器是一个实现了特定 HTPP 协议方面的惯例。通常协议拦截器希望作用于一个特定头部信息上,或者一族收到报文的相关头部信息,或使用一个特定的头 部或一族相关的头部信息填充发出的报

30、文。协议拦截器也可以操纵包含在报文中的内容实体,透明的内容压缩/解压就是一个很好的示例。通常情况下这是由包装器 实体类使用了“装饰者”模式来装饰原始的实体完成的。一些协议拦截器可以从一个逻辑单元中来结合。协议拦截器也可以通过共享信息来共同合作-比如处理状态-通过 HTTP 执行上下文。协议拦截器可以使用 HTTP 内容来为一个或多个连续的请求存储一个处理状态。通常拦截器执行的顺序不应该和它们基于的特定执行上下文状态有关。如果协议拦截器有相互依存关系,那么它们必须按特定顺序来执行,正如它们希望执行的顺序一样,它们应该在相同的序列中被加到协议处理器。协议拦截器必须实现为线程安全的。和 Servle

31、t 相似,协议拦截器不应该使用实例变量,除非访问的那些变量是同步的。这个示例给出了本地内容在连续的请求中怎么被用于持久一个处理状态的:DefaultHttpClient httpclient = new DefaultHttpClient();HttpContext localContext = new BasicHttpContext();AtomicInteger count = new AtomicInteger(1);localContext.setAttribute(“count“, count);httpclient.addRequestInterceptor(new HttpRe

32、questInterceptor() public void process(final HttpRequest request,final HttpContext context) throws HttpException, IOException AtomicInteger count = (AtomicInteger) context.getAttribute(“count“);request.addHeader(“Count“, Integer.toString(count.getAndIncrement(););HttpGet httpget = new HttpGet(“http:

33、/localhost/“);for (int i = 0; i 10; i+) HttpResponse response = httpclient.execute(httpget, localContext);HttpEntity entity = response.getEntity();if (entity != null) entity.consumeContent();1.6 HTTP 参数HttpParams 接口代表了定义组件运行时行为的一个不变的值的集合。很多情况下,HttpParams 和 HttpContext 相似。二者之间的主要区别是它们在运行时 使用的不同。这两个接口

34、表示了对象的集合,它们被视作为访问对象值的键的 Map,但是服务于不同的目的:HttpParams 旨在包含简单对象:整型,浮点型,字符串,集合,还有运行时不变的对象。HttpParams 希望被用在 “一次写入-多处准备”模式下。HttpContext 旨在包含很可能在HTTP 报文处理这一过程中发生改变的复杂对象HttpParams 的目标是定义其它组件的行为。通常每一个复杂的组件都有它自己的HttpParams 对象。 HttpContext 的目标是来表示一个 HTTP 处理的执行状态。通常相同的执行上下文在很多合作的对象中共享。1.6.1 参数层次在 HTTP 请求执行过程中,Htt

35、pRequest 对象的 HttpParams 是和用于执行请求的HttpClient 实例的 HttpParams 联系在一 起的。这使得设置在 HTTP 请求级别的参数优先于设置在 HTTP 客户端级别的 HttpParams。推荐的做法是设置普通参数对所有的在 HTTP客户端级 别的 HTTP 请求共享,而且可以选择性重写具体在 HTTP 请求级别的参数。DefaultHttpClient httpclient = new DefaultHttpClient();httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL

36、_VERSION,HttpVersion.HTTP_1_0);httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,“UTF-8“);HttpGet httpget = new HttpGet(“http:/ HttpRequestInterceptor() public void process(final HttpRequest request,final HttpContext context) throws HttpException, IOException System.out.pri

37、ntln(request.getParams().getParameter(CoreProtocolPNames.PROTOCOL_VERSION);System.out.println(request.getParams().getParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET);System.out.println(request.getParams().getParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE);System.out.println(request.getParams().g

38、etParameter(CoreProtocolPNames.STRICT_TRANSFER_ENCODING););输出内容为:HTTP/1.1UTF-8falsenull1.6.2 HTTP 参数 beanHttpParams 接口允许在处理组件的配置上很大的灵活性。很重要的是,新的参数可以被引入而不会影响老版本的二进制兼容性。然而,和常规的 Java bean 相比,HttpParams 也有一个缺点:HttpParams 不能使用 DI 框架来组合。为了缓解这个限制,HttpClient 包含了一些 bean 类,它们可以用来按顺序使用标准的 Java eban 惯例初始化 HttpP

39、arams 对象。HttpParams params = new BasicHttpParams();HttpProtocolParamBean paramsBean = new HttpProtocolParamBean(params);paramsBean.setVersion(HttpVersion.HTTP_1_1);paramsBean.setContentCharset(“UTF-8“);paramsBean.setUseExpectContinue(true);System.out.println(params.getParameter(CoreProtocolPNames.PR

40、OTOCOL_VERSION);System.out.println(params.getParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET);System.out.println(params.getParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE);System.out.println(params.getParameter(CoreProtocolPNames.USER_AGENT);输出内容为:HTTP/1.1UTF-8falsenull1.7 HTTP 请求执行参数这些参数会影响到请求执行

41、的过程:http.protocol.version:如果没有在请求对象中设置明确的版本信息,它就定义了使用的HTTP 协议版本。这个参数期望得到一个 ProtocolVersion 类型的值。如果这个参数没有被设置,那么就使用 HTTP/1.1。http.protocol.element-charset:定义了编码 HTTP 协议元素的字符集。这个参数期望得到一个 java.lang.String 类型的值。如果这个参数没有被设置,那么就使用 US-ASCII。http.protocol.eontent-charset:定义了为每个内容主体编码的默认字符集。这个参数期望得到一个 java.la

42、ng.String 类型的值。如果这个参数没有被设置,那么就使用 ISO-8859-1。http.useragent:定义了头部信息 User-Agent 的内容。这个参数期望得到一个java.lang.String 类型的值。如果这个参数没有被设置,那么 HttpClient 将会为它自动生成一个值。http.protocol.strict-transfer-encoding:定义了响应头部信息中是否含有一个非法的Transfer-Encoding,都要拒绝掉。http.protocol.expect- continue:为包含方法的实体激活 Expect: 100-Continue 握手。

43、Expect: 100-Continue 握手的目的是允许客户端使用请求体发送一个请求信息来决定源服务器是否希望在客户端发送请求体之前得到这个请求(基于请求头部信 息) 。Expect: 100-Continue 握手的使用可以对需要目标服务器认证的包含请求的实体(比如 POST 和PUT)导致明显的性能改善。Expect: 100-Continue 握手应该谨慎使用,因为它和 HTTP 服务器,不支持 HTTP/1.1协议的代理使用会引起问题。这个参数期望得到一个 java.lang.Boolean 类型的值。如果这个参数没有被设置,那么 HttpClient 将会试图使用握手。http.protocol.wait- for-continue:定义了客户端应该等待100-Continue 响应最大的毫秒级时间间隔。这个参数期望得到一个 java.lang.Integer 类型的值。如果这个参数没有被设置,那么 HttpClient 将会在恢复请求体传输之前为确认等待 3秒。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报