第一章
1.基础
1.1.执行请求
HttpClient的最重要的功能是执行HTTP方法。 HTTP方法的执行涉及到一个或多个HTTP请求/的HTTP响应交换,通常由HttpClient在内部处理。的用户预计将提供一个请求对象执行,HttpClient的预计发送请求到目标服务器返回一个相应的响应对象,或者抛出一个异常(如果执行不成功)。
很自然的HttpClient API的主要切入点是HttpClient的接口,它定义了上述合同。
下面是一个例子的请求执行过程中,在其最简单的形式中:
HttpClient 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(); try { // 插入代码 } finally { instream.close(); } }
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。
的Request-URI是一个统一资源标识符标识资源在其上应用的要求。 HTTP请求URI包括协议方案,主机名,可选的端口,资源路径,可选的查询,和可选的片段。
如下:
HttpGet httpget = new HttpGet( "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");
HttpClient提供UriBuilder的实用工具类来简化创建和修改请求的URI。
用法如下:
URIBuilder builder = new URIBuilder(); builder.setScheme("http").setHost("www.google.com").setPath("/search") .setParameter("q", "httpclient") .setParameter("btnG", "Google Search") .setParameter("aq", "f") .setParameter("oq", ""); URI uri = builder.build(); HttpGet httpget = new HttpGet(uri); System.out.println(httpget.getURI());
控制台输出:
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
1.1.2. HTTP响应
HTTP响应是由服务器发送的消息返回给客户端后,接收和解释请求消息。该消息的第一行包含一个数字状态代码及其相关的文本短语的协议版本。
代码如下:
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); System.out.println(response.getProtocolVersion()); System.out.println(response.getStatusLine().getStatusCode()); System.out.println(response.getStatusLine().getReasonPhrase()); System.out.println(response.getStatusLine().toString());
输出:
HTTP/1.1 200 OK HTTP/1.1 200 OK
1.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", "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=/; domain=localhost Set-Cookie: c2=b; path="/", c3=c; domain="localhost" 2
获得一个给定类型的所有标头的最有效的方法是使用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=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=localhost Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
它还提供了方便的方法来解析HTTP消息到个人的头元素。
代码如下:
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=b; path=/"//", c3=c; domain=/"localhost/""); HeaderElementIterator it = new BasicHeaderElementIterator( response.headerIterator("Set-Cookie")); while (it.hasNext()) { HeaderElement elem = it.nextElement(); System.out.println(elem.getName() + " = " + elem.getValue()); NameValuePair[] params = elem.getParameters(); for (int i = 0; i < params.length; i++) { System.out.println(" " + params[i]); } }
输出:
c1 = a path=/ domain=localhost c2 = b path=/ c3 = c domain=localhost
1.1.4. HTTP实体
HTTP报文可以携带的请求或响应相关的内容实体。实体可以被发现在某些要求,在某些反应中,因为它们是可选的。使用了实体的被称为作为实体包含请求的请求。 HTTP规范定义了两个实体内附请求方法:POST和PUT。响应通常期望附上一个内容实体。但也有例外情况,比如HEAD方法和204没有内容,304没有修改,205重置内容响应。
HttpClient的区分三种类型的实体,取决于其内容:
流媒体:内容从流中获得,或在飞行中产生。特别是,此类别包括被从HTTP响应接收实体。流式传输的实体一般不可重复的。
自包含的独立的:内容在内存中,或获得通过,是独立的连接或其它实体。自足的实体一般都是重复的。这种类型的实体将主要用于封闭HTTP请求的实体。
包装:内容是从另一个实体。
流媒体内容从一个HTTP响应时,这个区别是非常重要的连接管理。对于请求所创建的应用程序和实体只发送使用HttpClient之间的差异流和 自包含的意义不大。在这种情况下,建议考虑非重复的实体作为流式传输,可重复的实体作为自包含的独立实体传输。
1.1.4.1.重复实体
一个实体可以是可重复的,这意味着它的内容可以被读取一次以上。那么它肯定是自包含实体(如ByteArrayEntity或StringEntity)
1.1.4.2.使用HTTP实体
由于一个实体可以代表二进制和字符的内容,它支持的字符编码(支持后者,即字符内容)。
实体被创建当使用封闭内容执行请求时,或当一个成功的请求和响应体将结果返回给客户端。
从实体中读取内容,可以通过HttpEntity#getContent()方法,该方法返回的java.io.InputStream,或一个可以提供一个输出流的HttpEntity#writeTo(OutputStream中)方法的输入流,后,将返回所有内容已被写入给定的流。
当实体已接收传入的消息,该方法的HttpEntity#的getContentType()和HttpEntity#getContentLength()方法可以用于读取常见的元数据,如Content-Type和Content-Length的头文件(如果有的话)。由于Content-Type Header可以包含文本的字符编码为MIME类型,如text / plain或text / html类型的HttpEntity#getContentEncoding()方法用来读取此信息。如果标题是不可用的,长度为-1将返回NULL的内容类型。如果Content-Type Header可用,将返回一个Header对象。
当创建一个实体为一个传出的消息时,此元数据必须被提供由该实体的创造者。
用法如下:
StringEntity myEntity = new StringEntity("important message", ContentType.create("text/plain", "UTF-8")); System.out.println(myEntity.getContentType()); System.out.println(myEntity.getContentLength()); System.out.println(EntityUtils.toString(myEntity)); System.out.println(EntityUtils.toByteArray(myEntity).length);
输出:
Content-Type: text/plain; charset=utf-8 17 important message 17
1.1.5.确保低级别资源释放
为了确保正确释放系统资源,必须关闭与实体相关的内容流。
示例代码如下:
HttpResponse response; HttpEntity entity = response.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); try { // 插入代码 } finally { instream.close(); } }
还需要注意的HttpEntity#writeTo(OutputStream中)方法,以确保正确释放系统资源,一旦实体已经完全写出来。如果这种方法获得的java.io.InputStream实例调用的HttpEntity#getContent()方法,它也有望在finally子句中关闭流。
当工作流实体,可以使用的EntityUtils#consume(HttpEntity)方法来确保的实体内容已经完全消耗掉,底层流已关闭。
可以存在的情况下,然而,当只有一小部分的整个响应内容的需要进行检索和用于消耗的剩余的内容,和可重复使用的连接的性能损失是过高的,在这种情况下,人们可以简单地通过调用终止请求HttpUriRequest#abort()方法。
用法如下:
HttpGet httpget = new HttpGet("http://localhost/"); HttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); int byteOne = instream.read(); int byteTwo = instream.read(); // Do not need the rest httpget.abort(); }
连接将不会被重用,但其持有的所有级别的资源将被正确地释放。
1.1.6.消费的实体内容
消费内容的实体的推荐方法是通过使用它的HttpEntity#getContent()方法或者HttpEntity#writeTo(OutputStream中)方法。 HttpClient的还配备了EntityUtils类,它暴露了一些静态方法更方便地阅读的内容或信息从一个实体。使用这个类的方法,而不是直接读取的java.io.InputStream,可以检索整个内容体中的字符串/字节数组。然而,使用强烈劝阻EntityUtils除非响应实体从受信任的HTTP服务器发起的,并且是已知的有限长度。
用法如下:
HttpGet httpget = new HttpGet("http://localhost/"); HttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); if (entity != null) { long len = entity.getContentLength(); if (len != -1 && len < 2048) { System.out.println(EntityUtils.toString(entity)); } else { // Stream content out } }
在某些情况下,它可能是必要的,以便能够不止一次读取实体内容。在这种情况下实体的内容必须以某种方式被缓冲,无论是在内存或磁盘上。的最简单的方法来完成,这是通过包装原始实体与BufferedHttpEntity类。这将导致原来的实体被读取到一个内存中的缓冲区的内容。在所有其他方面的的实体包装将有原来的。
用法如下:
HttpGet httpget = new HttpGet("http://localhost/"); HttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); if (entity != null) { entity = new BufferedHttpEntity(entity); }
1.1.7.生成实体内容
HttpClient提供了几个类,可以有效地用于流媒体内容通过HTTP连接。这些类的实例可以与实体内附请求,比如POST和PUT为了封闭传出HTTP请求的实体内容。 HttpClient提供了几类最常见的数据容器,如字符串,字节数组输入流,文件:StringEntity,ByteArrayEntity,InputStreamEntity和FileEntity。
用法如下:
File file = new File("somefile.txt"); FileEntity entity = new FileEntity(file, ContentType.create("text/plain", "UTF-8")); HttpPost httppost = new HttpPost("http://localhost/action.do"); httppost.setEntity(entity);
请注意InputStreamEntity是不可重复的,因为它只能从底层数据流中读取一次。一般来说,建议实现一个自定义的HttpEntity类是自包含的,而不是使用通用的InputStreamEntity。的FileEntity可以是一个很好的起点。
1.1.7.1. HTML表单
许多应用程序需要模拟的过程中,提交一个HTML表单,例如,在登录到Web应用程序或提交的输入数据。 HttpClient提供的实体类UrlEncodedFormEntity以促进这一进程。
用法如下:
List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("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编码参数进行编码,并产生以下内容:
param1=value1¶m2=value2
1.1.7.2.内容分块
一般来说,建议让HttpClient选择最合适的传输编码在正在传输的HTTP消息的属性的基础上。这是可能的,但是,通知HttpClient的块编码是首选的HttpEntity#setChunked()设置为true。请注意的HttpClient将使用这个标志作为提示。使用HTTP协议的版本不支持块编码,如HTTP/1.0时,该值将被忽略。
用法如下:
StringEntity entity = new StringEntity("important message", "text/plain; charset=/"UTF-8/""); entity.setChunked(true); HttpPost httppost = new HttpPost("http://localhost/acrtion.do"); httppost.setEntity(entity);
1.1.8.响应处理程序
最简单,最方便的方式来处理响应的handleResponse ResponseHandler的接口,其中包括方法的HttpResponse响应。这种方法完全免除了用户不必担心连接管理。当使用ResponseHandler的,HttpClient会自动照顾,确保释放连接返回到连接管理器,无论该请求是否执行成功或导致异常。
用法如下:
HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost/"); ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() { public byte[] handleResponse( HttpResponse response) throws ClientProtocolException, IOException { HttpEntity entity = response.getEntity(); if (entity != null) { return EntityUtils.toByteArray(entity); } else { return null; } } }; byte[] response = httpclient.execute(httpget, handler);
1.2. HTTP的执行上下文
最初的HTTP被设计为一个无状态的,面向响应请求的协议。然而,现实世界的应用程序通常需要能够坚持一些逻辑相关的请求 - 响应交换状态信息通过。为了使应用程序能够保持状态,HttpClient允许在一个特定的执行环境,称为HTTP上下文中执行HTTP请求的处理。如果同样的情况下连续请求之间重用,多个逻辑相关的请求可以参与到一个逻辑会话。 HTTP上下文功能类似于到一个java.util.Map <String,对象>。它只是一个任意命名的值的集合。应用程序可以填充上下文属性之前请求执行或已经完成检查的情况下执行后。
HttpContext的可以包含任意的对象,因此可能是不安全的多个线程之间共享。建议执行的每个线程维护自己的上下文。
在HTTP请求执行的过程中,HttpClient的添加下列属性到执行上下文:
ExecutionContext.HTTP_CONNECTION ='http.connection:HttpConnection实例代表实际连接到目标服务器。
ExecutionContext.HTTP_TARGET_HOST ='http.target_host“:一个HttpHost实例代表连接的目标。
ExecutionContext.HTTP_PROXY_HOST ='http.proxy_host“:连接代理的一个HttpHost例如,如果使用
ExecutionContext.HTTP_REQUEST ='http.request“:HttpRequest实例代表实际的HTTP请求。最终的HttpRequest对象的执行上下文中总是代表着国家的消息_exactly_,它被发送到目标服务器。每默认情况下HTTP/1.0和HTTP/1.1使用相对的URI请求。但是,如果请求是在非隧道模式,然后通过代理发送的URI将是绝对的。
ExecutionContext.HTTP_RESPONSE ='http.response“的HttpResponse实例代表实际的HTTP响应。
ExecutionContext.HTTP_REQ_SENT ='http.request_sent':java.lang.Boolean对象代表的标志,表示实际的请求是否已被完全传输到所述连接目标。
比如,为了以确定最终的重定向目标,一个可以检查后的请求执行的的http.target_host属性的值:
用法如下:
DefaultHttpClient httpclient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpGet httpget = new HttpGet("http://www.google.com/"); HttpResponse response = httpclient.execute(httpget, localContext); HttpHost target = (HttpHost) localContext.getAttribute( ExecutionContext.HTTP_TARGET_HOST); System.out.println("Final target: " + target); HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); }
输出:
Final target: http://www.google.ch
1.3.异常处理
HttpClient可以抛出两种类型的异常:java.io.IOException异常情况下的I / O故障,如超时插座或插座复位和HttpException异常信号,如违反HTTP协议的HTTP失败。通常I/ O错误被视为非致命性和可恢复的,而HTTP协议错误被认为是致命的,并不能自动恢复的。
1.3.1. HTTP运输安全
重要的是要明白,HTTP协议的所有类型的应用不能很好地适合。 HTTP是一个简单的面向请求/响应协议,该协议最初是为了支持静态或动态生成的内容检索。它从来没有被支持的事务性操作。例如,HTTP服务器将考虑其继续履行合同的一部分,如果它成功地接收和处理请求,生成一个响应返回给客户端发送一个状态码。服务器不会试图回滚事务,如果客户端没有接收到其整体的响应,由于读取超时,要求取消或系统崩溃。如果客户决定重试相同的请求时,服务器将不可避免地最终执行相同的交易超过一次。在某些情况下,这可能会导致应用数据损坏或不一致的应用程序的状态。
虽然HTTP从来没有被设计为支持事务处理,它仍然可以被用来作为传输协议的关键任务应用程序提供了某些条件得到满足。为了确保HTTP传输层安全,系统必须确保在应用层上的幂等的HTTP方法。
1.3.2.幂等方法
HTTP/1.1规范定义了一个幂等方法,
[方法也可以有属性的“幂等”,(除了错误或过期问题),N>0的相同请求的副作用是作为一个单一的请求]
换句话说,应用程序应该以确保,它准备多个执行的方法相同的方法来处理的影响。这可以实现,例如,通过提供一个唯一的交易ID,和由其他装置,避免相同的逻辑操作的执行。
请注意,这个问题是不是特定的HttpClient。基于浏览器的应用程序相关的HTTP方法非幂等完全相同的问题。
HttpClient假设非实体内附方法,如GET和HEAD是幂等与实体内附方法,如POST和PUT,不。
1.3.3.异常自动恢复
默认情况下的HttpClient尝试自动恢复从I/ O异常。默认的自动恢复机制被限制在只有少数例外,被称为是安全的。
HttpClient不会尝试恢复从任何逻辑或HTTP协议错误(从HttpException类派生)。
HttpClient将会自动重新被假定为幂等的方法。
HttpClient会自动重试失败的方法,与运输异常的HTTP请求仍然被传输到目标服务器(即请求没有被完全传输到服务器)。
1.3.4.请求重试处理
为了使一个自定义的异常恢复机制应该提供一个实现HttpRequestRetryHandler接口的。
用法如下:
DefaultHttpClient httpclient = new DefaultHttpClient(); HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() { public boolean retryRequest( IOException exception, int executionCount, HttpContext context) { if (executionCount >= 5) { // Do not retry if over max retry count return false; } if (exception instanceof InterruptedIOException) { // Timeout return false; } if (exception instanceof UnknownHostException) { // Unknown host return false; } if (exception instanceof ConnectException) { // Connection refused return false; } if (exception instanceof SSLException) { // SSL handshake exception return false; } HttpRequest request = (HttpRequest) context.getAttribute( ExecutionContext.HTTP_REQUEST); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { // Retry if the request is considered idempotent return true; } return false; } }; httpclient.setHttpRequestRetryHandler(myRetryHandler);
1.4.中止请求
在某些情况下,HTTP请求执行失败,由于在目标服务器上或在客户端发出太多的并发请求的高负荷的预期时间框架内完成。在这种情况下,可能有必要提前终止的要求和解锁的执行线程阻塞在一个I / O操作。通过调用HttpUriRequest#abort()方法,可以在任何阶段的执行中止正在执行的HTTP请求,由HttpClient。此方法是线程安全的,可以从任何线程调用。当一个HTTP请求被中止它的执行线程 - 即使目前正阻塞在I / O操作 - 抛出一个InterruptedIOException异常保证解除封锁
1.5. HTTP协议拦截器
TH HTTP协议拦截器是一个例行程序,实现了HTTP协议的一个具体方面。通常协议拦截一个特定的页眉或一组相关的头传入的消息后,预计将采取行动或填充一个特定的页眉或一组相关的头传出消息。协议拦截器也可以操作包含在报文中的内容实体 - 透明的内容压缩/解压就是一个很好的例子。这通常是通过使用“装饰者”模式,其中一个包装实体类是用来装饰的原始实体。一些协议拦截器可以被组合以形成一个逻辑单元。
协议拦截器可以合作,共享信息 - 如处理状态 - 通过HTTP的执行上下文。协议拦截器可以使用HTTP上下文来存储一个请求或几个连续的请求的处理状态。
通常情况下,拦截器执行顺序应该没有关系,只要他们不依赖于一个特定状态下的执行上下文。如果协议拦截器有相互依存,因此,必须在一个特定的顺序执行的,他们应该被添加到其预期的执行顺序相同的顺序协议处理器中。
协议拦截器必须实现为线程安全的。 Servlet相似,协议拦截器不应该使用实例变量,除非获得这些变量的同步。
这是一个例子,局部范围内可用于保存处理连续请求之间的状态:
用法如下:
DefaultHttpClient httpclient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); AtomicInteger count = new AtomicInteger(1); localContext.setAttribute("count", count); httpclient.addRequestInterceptor(new HttpRequestInterceptor() { 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://localhost/"); for (int i = 0; i < 10; i++) { HttpResponse response = httpclient.execute(httpget, localContext); HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); }
1.6. HTTP参数
HttpParams接口代表不变的值的集合,定义运行时行为的一个组成部分。在许多方面,HttpParams的是类似的HttpContext。在运行时,两者之间的主要区别在于它们的使用。这两个接口的集合被组织为一个键映射对象值的对象,但服务于不同的目的:
1.HttpParams意在包含简单对象:整数,双打,字符串,集合和对象在运行时保持不变的。
2.HttpParams预计将在“一次写入 - 多处准备”模式。 HttpContext的目的是包含在HTTP报文处理过程中很可能发生变异的复杂对象。
3.HttpParams的目标是定义一个行为的其他组件。一般每个复杂的组件都有它自己的HttpParams对象。 HttpContext的目标是代表一个HTTP处理的执行状态。通常情况下,相同的执行上下文之间共享许多合作对象。
1.6.1.参数层次
在HTTP请求执行的HttpParams的HttpRequest对象的过程中是连在一起的,用于执行请求的HttpClient的实例HttpParams的。这使得在HTTP请求级别的参数设置优先于设置在HTTP客户端级别的HttpParams。推荐的做法是共享所有的HTTP请求HTTP客户端级别,选择性地覆盖在HTTP请求级别的具体参数,制定共同的参数。
用法如下:
DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0); // Default to HTTP 1.0 httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); HttpGet httpget = new HttpGet("http://www.google.com/"); httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); // Use HTTP 1.1 for this request only httpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE); httpclient.addRequestInterceptor(new HttpRequestInterceptor() { public void process( final HttpRequest request, final HttpContext context) throws HttpException, IOException { System.out.println(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().getParameter( CoreProtocolPNames.STRICT_TRANSFER_ENCODING)); } });
输出:
HTTP/1.1 UTF-8 false null
1.6.2. HTTP参数豆类的
HttpParams接口允许一个极大的灵活性,在处理组件的配置。最重要的是,可以引入新的参数,而不影响旧版本的二进制兼容性。然而,HttpParams的也有一定的劣势,相比常规的Java bean:HttpParams不能使用DI框架的组装。为了减轻限制,HttpClient的还包括一些bean类,它们可用于以初始化HttpParams的对象,使用标准的Java bean约定。
用法如下:
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.PROTOCOL_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.1 UTF-8 false null
1.7. HTTP请求执行参数
请求执行的过程中,可能会影响这些参数:
CoreProtocolPNames.PROTOCOL_VERSION
='http.protocol.version':定义HTTP协议版本,如果没有明确设定的请求对象。这个参数期望得到一个ProtocolVersion类型的值。如果该参数没有设置HTTP/1.1将被使用。
CoreProtocolPNames.HTTP_ELEMENT_CHARSET
='http.protocol.element-charset':定义使用的字符集编码HTTP协议的元素。这个参数期望得到一个java.lang.String类型的值。如果该参数没有设置US-ASCII将被使用。
CoreProtocolPNames.HTTP_CONTENT_CHARSET
='http.protocol.content-charset':定义要使用的每默认为内容主体编码字符集。这个参数期望得到一个java.lang.String类型的值。如果该参数没有设置ISO-8859-1将被使用。
CoreProtocolPNames.USER_AGENT
='http.useragent':定义的User-Agent头的内容。这个参数期望得到一个java.lang.String类型的值。如果该参数没有设置,HttpClient会自动生成一个值。
CoreProtocolPNames.STRICT_TRANSFER_ENCODING
='http.protocol.strict-transfer-encoding':定义是否应拒绝响应无效Transfer-Encoding头。这个参数期望得到一个java.lang.Boolean类型的值。如果该参数没有设置,无效Transfer-Encoding值将被忽略。
CoreProtocolPNames.USE_EXPECT_CONTINUE
='http.protocol.expect-continue':激活预计:100继续握手的实体内附方法。之前的客户端发送请求的期待:100继续握手的目的是让客户端,如果原始服务器发送一个请求消息,请求主体,以确定是愿意接受的请求(根据请求标头)身体。使用的期待:100继续握手会导致实体内附目标服务器的身份验证请求(如POST和PUT),需要在一个显着的性能改善。预计:100继续握手应该谨慎使用,因为它可能会导致问题,不支持HTTP/1.1协议的HTTP服务器和代理。这个参数期望得到一个java.lang.Boolean类型的值。如果该参数没有设置,HttpClient的将不会尝试使用握手。
CoreProtocolPNames.WAIT_FOR_CONTINUE
='http.protocol.wait-for-continue':定义的客户端应该花了100继续响应的等待时间(以毫秒为单位)的最长期限。这个参数期望得到一个java.lang.Integer类型的值。如果该参数没有设置,HttpClient将等待3秒恢复传输请求体之前,可以先进行确认。