1. HttpClient接口总览
HttpClient接口代表了HTTP请求执行的核心协议:用户提供请求对象交给HttpClient执行,HttpClient负责把请求对象传递给服务器,然后返回响应对象,或者抛出异常。
HttpClient作为Facade,把具体实现的细节交给了handlers和strategies.
HttpClient实例是线程安全的,鼓励HttpClient实例的重用。对于不再使用的CloseableHttpClient,要关闭。
2. HttpContext
HttpClient.execute里的HttpContext参数能让相关的请求在一个会话中执行,只要这些请求的执行使用同一个HttpContext对象。HttpClient在执行请求过程中会向HttpContext对象里添加HttpConnection, HttpHost, HttpRoute, HttpRequest, HttpResponse, transmitted flag, RequestConfig, Redirect URI List. 使用HttpClientContext.adapt方法,能把HttpContext对象适配成HttpClientContext,便于对这些属性的读取和设置。
3. 请求执行过程
HttpClient的请求执行过程是由ClientExecChain组成的链条。
请求执行链条过程中的ProtocolExec环节,负责完成与HTTP规范相关的要求。ProtocolExec将工作交给了HttpProcessor来完成,HttpProcessor由请求拦截器链和响应拦截器链构成。请求拦截器和响应拦截器完成实际的HTTP协议相关工作。
4. 异常处理
HttpRequestExecutor和请求执行链上的ClientExecChain的execute方法,HttpProcessor和拦截器的process方法都会抛出两类异常:
IOException: 与I/O错误相关的异常,例如socket timeout, socket reset等。此类异常可以认为是非致命的,可恢复的异常。恢复逻辑由应用提供。
HttpException: 与HTTP协议错误相关的异常,此类错误是致命的,无法恢复。
HttpClient的execute方法把捕获到的HttpException异常包装成ClientProtocolException,该异常继承自IOException, 这样调用方可以统一处理这两类异常。
5. 重试处理器
请求执行链上的RetryExec询问HttpRequestRetryHandler是否进行重试。是否进行重试主要考虑两点:发生的异常类型是支持重试,发送的请求类型是否支持重试。
hc提供的默认重试处理器DefaultHttpRequestRetryHandler的决策逻辑为:
- 只支持对IOException进行重试,并且不支持以下IOException: InterruptedIOException, UnknownHostException, ConnectException, SSLException
- 不会对携带Entity的请求进行重试,即不会对HttpPut, HttpPost, HttpPatch进行重试。也就是说,不对不满足幂等性的HTTP方法重试。
- 请求未abort
6. 重导向策略
请求执行链上的RedirectExec询问RedirectStrategy是否进行重导向以及重导向的地址。
是否进行重导向主要考虑发送的请求类型和响应的状态码。hc提供的DefaultRedirectStrategy仅支持302, 301, 307和303响应,同时仅支持HttpGet和HttpHead请求。
DefaultRedirectStrategy根据响应头的location信息来计算重导向地址,并且能发现循环导向并抛出异常。
调用HttpUriRequest.abort()方法可以中止请求的执行。如果请求执行线程正处于阻塞状态,中止请求就会以抛出InterruptedIOException的方式来中止。