变量
//方法连接器
private ConnectMethod connectMethod;
//HTTP状态
private HttpState state;
//主机配置
private HostConfiguration hostConfiguration;
//HTTP连接管理器
private HttpConnectionManager connectionManager;
//HTTP客户端参数
private HttpClientParams params;
//HTTP连接
private HttpConnection conn;
//是否释放连接
private boolean releaseConnection = false;
//授权挑战处理器
private AuthChallengeProcessor authProcessor = null;
//重定向位置
private Set redirectLocations = null;
构造方法
public HttpMethodDirector(HttpConnectionManager connectionManager, HostConfiguration hostConfiguration, HttpClientParams params, HttpState state) {
this.connectionManager = connectionManager;
this.hostConfiguration = hostConfiguration;
this.params = params;
this.state = state;
this.authProcessor = new AuthChallengeProcessor(this.params);
}
主要执行方法execute
具体解析可看代码中的注释:
public void executeMethod(HttpMethod method) throws IOException, HttpException {
if(method == null) {
throw new IllegalArgumentException("Method may not be null");
} else {
this.hostConfiguration.getParams().setDefaults(this.params);
method.getParams().setDefaults(this.hostConfiguration.getParams());
//获取传入的缺省标题,这个缺省的标题可以由调用方传递
Collection defaults = (Collection)this.hostConfiguration.getParams().getParameter("http.default-headers");
if(defaults != null) {
Iterator maxRedirects = defaults.iterator();
while(maxRedirects.hasNext()) {
//将自定义的Header设置到Http方法的头部
method.addRequestHeader((Header)maxRedirects.next());
}
}
try {
//获取最大重定向次数,如果没有传这个参数则默认重定向100次
int var9 = this.params.getIntParameter("http.protocol.max-redirects", 100);
//计数,从0开始
int redirectCount = 0;
while(true) {
if(this.conn != null && !this.hostConfiguration.hostEquals(this.conn)) {
//如果此链接存在并且,主机配置相同则先解锁,然后释放此链接
this.conn.setLocked(false);
this.conn.releaseConnection();
this.conn = null;
}
if(this.conn == null) {
//使用连接管理器根据主机配置参数和超时时间创建链接
this.conn = this.connectionManager.getConnectionWithTimeout(this.hostConfiguration, this.params.getConnectionManagerTimeout());
//将此条链接锁标记位至锁定状态
this.conn.setLocked(true);
//由http.authentication.preemptive字段获取这个参数
if(this.params.isAuthenticationPreemptive() || this.state.isAuthenticationPreemptive()) {
LOG.debug("Preemptively sending default basic credentials");
//如果身份验证优先则设置抢占,设置抢占和身份验证
method.getHostAuthState().setPreemptive();
method.getHostAuthState().setAuthAttempted(true);
if(this.conn.isProxied() && !this.conn.isSecure()) {
//如果这条链接使用了代理并且是不安全的则,设置代理的抢占和身份验证
method.getProxyAuthState().setPreemptive();
method.getProxyAuthState().setAuthAttempted(true);
}
}
}
//Http方法获取认证
this.authenticate(method);
//执行时重试
this.executeWithRetry(method);
if(this.connectMethod != null) {
this.fakeResponse(method);
break;
}
//设置重定向标志位为false
boolean retry = false;
if(this.isRedirectNeeded(method) && this.processRedirectResponse(method)) {
//如果method方法需要重定向并且重定向响应返回true,则将重定向标志位设置为true
retry = true;
//重定向计数器加1
++redirectCount;
//如果超过了设置的最大重定向数则抛出重定向异常
if(redirectCount >= var9) {
LOG.error("Narrowly avoided an infinite loop in execute");
throw new RedirectException("Maximum redirects (" + var9 + ") exceeded");
}
if(LOG.isDebugEnabled()) {
LOG.debug("Execute redirect " + redirectCount + " of " + var9);
}
}
if(this.isAuthenticationNeeded(method) && this.processAuthenticationResponse(method)) {
//如果method方法需要身份验证且处理身份验证过程响应返回true则将重定向标志位设置为true
LOG.debug("Retry authentication");
retry = true;
}
if(!retry) {
//如果重定向为false则执行break;
break;
}
if(method.getResponseBodyAsStream() != null) {
//关闭输入流
method.getResponseBodyAsStream().close();
}
}
} finally {
if(this.conn != null) {
this.conn.setLocked(false);
}
if((this.releaseConnection || method.getResponseBodyAsStream() == null) && this.conn != null) {
this.conn.releaseConnection();
}
}
}
}