第五章
5. HTTP客户端服务
5.1. HttpClient的门面
HttpClient接口代表了最重要的HTTP请求执行的合同。它施加任何限制或特定的细节上请求执行过程中,连接管理,状态管理,认证和离开的具体处理重定向到具体实现。这应该更容易来装饰接口提供额外的功能,如响应内容缓存。
DefaultHttpClient HttpClient接口的默认实现。这个类充当门面了一些特殊的的目的处理程序或策略接口实现,负责处理HTTP协议的某一方面,如重定向或的认证处理或决策关于持久性连接,并保持活动的持续时间。这使用户能够选择性地替换这些方面的习俗,特定于应用程序的默认实现。
用法如下:
DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration( HttpResponse response, HttpContext context) { long keepAlive = super.getKeepAliveDuration(response, context); if (keepAlive == -1) { // Keep connections alive 5 seconds if a keep-alive value // has not be explicitly set by the server keepAlive = 5000; } return keepAlive; } });
DefaultHttpClient还保持一份协议拦截器,用于处理传出的请求,并传入响应,并提供用于管理那些拦截器的方法。新的协议拦截器可以被引入到协议处理器链,如果需要的话或删除。内部协议拦截器都存储在一个简单的java.util.ArrayList。它们的执行相同的自然秩序,因为它们添加到列表中。
用法如下:
DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.removeRequestInterceptorByClass(RequestUserAgent.class); httpclient.addRequestInterceptor(new HttpRequestInterceptor() { public void process( HttpRequest request, HttpContext context) throws HttpException, IOException { request.setHeader(HTTP.USER_AGENT, "My-own-client"); } });
DefaultHttpClient是线程安全的。建议这一类的同一个实例被重用多个请求的执行。当DefaultHttpClient实例不再需要,是走出去的范围,连接管理器,必须关闭与它相关的通过调用ClientConnectionManager编号shutdown()方法。
HttpClient httpclient = new DefaultHttpClient(); // Do something useful httpclient.getConnectionManager().shutdown();
5.2. HttpClient的参数
这些参数可用于自定义的行为的默认HttpClient的实现:
ClientPNames.HANDLE_REDIRECTS
='http.protocol.handle-redirects': 定义是否应自动处理重定向。这个参数期望得到一个java.lang.Boolean类型的值。如果该参数没有设置,HttpClient会自动处理重定向。
ClientPNames.REJECT_RELATIVE_REDIRECT
='http.protocol.reject-relative-redirect': 定义相对重定向是否应该被拒绝。 HTTP规范要求的位置值是一个绝对URI。这个参数期望得到一个java.lang.Boolean类型的值。如果该参数没有设置相对重定向将被允许。
ClientPNames.MAX_REDIRECTS
='http.protocol.max-redirects': 重定向到定义的最大数量。重定向数的限制是为了防止无限循环所造成的破碎的服务器端脚本。这个参数期望得到一个java.lang.Integer类型的值。如果该参数没有设置,不超过100重定向将被允许。
ClientPNames.ALLOW_CIRCULAR_REDIRECTS
='http.protocol.allow-circular-redirects': 定义循环重定向(重定向到同一个位置)是否应该被允许。 HTTP规范不够明确是否允许循环重定向,因此他们可以选择启用。这个参数期望得到一个java.lang.Boolean类型的值。如果该参数没有设置环形重定向将被禁止。
ClientPNames.CONNECTION_MANAGER_FACTORY_CLASS_NAME
='http.connection-manager.factory-class-name': 定义的默认ClientConnectionManager实现的类名。这个参数期望得到一个java.lang.String类型的值。如果该参数没有设置SingleClientConnManager将每默认情况下使用。
ClientPNames.VIRTUAL_HOST
='http.virtual-host': 定义的虚拟主机设置中使用的,而不是物理主机的主机头。这个参数期望得到一个HttpHost类型的值。将源自目标,因为它并不一定要指定一个HttpHost端口。如果该参数没有设置,目标主机的名称或IP地址(和端口,如果需要的话)将被使用。
ClientPNames.DEFAULT_HEADERS
='http.default-headers': 定义每默认情况下,每个请求要发送的请求报头。这个参数期望得到一个java.util.Collection类型Header对象。
ClientPNames.DEFAULT_HOST
='http.default-host': 定义了默认的主机。如果目标主机不明确,请求的URI(相对URI),将使用默认值。这个参数期望得到一个HttpHost类型的值。
5.3.自动处理重定向
HttpClient处理所有类型的重定向自动完成,无需用户干预的HTTP规范,明令禁止的除外。见其他(状态代码303)重定向POST和PUT请求转换为GET请求的HTTP规范所要求的。
5.4. HTTP客户端和执行上下文
DefaultHttpClient处理HTTP请求,请求执行的过程中,从来不应该改变不可变的对象。相反,它创建一个私人的可变副本的原始请求对象,其性质取决于执行上下文可以更新。因此,最终的目标主机和请求的URI的请求属性,如可确定已执行的请求后,通过检查本地HTTP上下文的内容。
最终的HttpRequest对象的执行上下文中总是代表着国家的消息_exactly_,它被发送到目标服务器。每默认情况下HTTP/1.0和HTTP/1.1使用相对的URI请求。但是,如果请求是在非隧道模式,然后通过代理发送的URI将是绝对的。
用法如下:
DefaultHttpClient httpclient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpGet httpget = new HttpGet("http://localhost:8080/"); HttpResponse response = httpclient.execute(httpget, localContext); HttpHost target = (HttpHost) localContext.getAttribute( ExecutionContext.HTTP_TARGET_HOST); HttpUriRequest req = (HttpUriRequest) localContext.getAttribute( ExecutionContext.HTTP_REQUEST); System.out.println("Target host: " + target); System.out.println("Final request URI: " + req.getURI()); // relative URI (no proxy used) System.out.println("Final request method: " + req.getMethod());
5.5.压缩响应内容
ContentEncodingHttpClient是一个简单的DefaultHttpClient的子类,增加了支持表示服务器,它支持gzip和deflate压缩的回应。这是通过现有的HTTP协议拦截器的API。根据响应的类型(文本将压缩以及与图像,这是典型的已经压缩的),这可以加快响应由于涉及的网络通信量的小,随着节省带宽的,它可以在移动的环境中是很重要。的拦截公布的API的一部分,可用于其他DefaultHttpClient实现RequestAcceptEncoding和ResponseContentEncoding。提供透明的处理gzip和deflate编码的,所以它不会是显而易见的,该处理的客户端发生。
ContentEncodingHttpClient httpclient = new ContentEncodingHttpClient(); HttpGet httpget = new HttpGet("http://www.yahoo.com/"); HttpResponse response = httpclient.execute(httpget); Header h = rsp.getFirstHeader("Content-Encoding"); if (h != null) { System.out.println("----------------------------------------"); System.out.println("Response is " + h.getValue() + " encoded"); System.out.println("----------------------------------------"); }
你也可以添加RequestAcceptEncoding 和ResponseContentEncoding拦截器到 DefaultHttpClient实例,如果需要的话。
DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.addRequestInterceptor(new RequestAcceptEncoding()); httpclient.addResponseInterceptor(new ResponseContentEncoding());