序
本文主要研究一下HttpClient的HttpRoutePlanner
HttpRoutePlanner
org/apache/http/conn/routing/HttpRoutePlanner.java
/**
* Encapsulates logic to compute a {@link HttpRoute} to a target host.
* Implementations may for example be based on parameters, or on the
* standard Java system properties.
* <p>
* Implementations of this interface must be thread-safe. Access to shared
* data must be synchronized as methods of this interface may be executed
* from multiple threads.
* </p>
*
* @since 4.0
*/
public interface HttpRoutePlanner {
/**
* Determines the route for a request.
*
* @param target the target host for the request.
* Implementations may accept {@code null}
* if they can still determine a route, for example
* to a default target or by inspecting the request.
* @param request the request to execute
* @param context the context to use for the subsequent execution.
* Implementations may accept {@code null}.
*
* @return the route that the request should take
*
* @throws HttpException in case of a problem
*/
HttpRoute determineRoute(HttpHost target,
HttpRequest request,
HttpContext context) throws HttpException;
}
HttpRoutePlanner接口定义了determineRoute方法,用于决定该请求的目标route
DefaultRoutePlanner
org/apache/http/impl/conn/DefaultRoutePlanner.java
/**
* Default implementation of an {@link HttpRoutePlanner}. It will not make use of
* any Java system properties, nor of system or browser proxy settings.
*
* @since 4.3
*/
@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
public class DefaultRoutePlanner implements HttpRoutePlanner {
private final SchemePortResolver schemePortResolver;
public DefaultRoutePlanner(final SchemePortResolver schemePortResolver) {
super();
this.schemePortResolver = schemePortResolver != null ? schemePortResolver :
DefaultSchemePortResolver.INSTANCE;
}
@Override
public HttpRoute determineRoute(
final HttpHost host,
final HttpRequest request,
final HttpContext context) throws HttpException {
Args.notNull(request, "Request");
if (host == null) {
throw new ProtocolException("Target host is not specified");
}
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final RequestConfig config = clientContext.getRequestConfig();
final InetAddress local = config.getLocalAddress();
HttpHost proxy = config.getProxy();
if (proxy == null) {
proxy = determineProxy(host, request, context);
}
final HttpHost target;
if (host.getPort() <= 0) {
try {
target = new HttpHost(
host.getHostName(),
this.schemePortResolver.resolve(host),
host.getSchemeName());
} catch (final UnsupportedSchemeException ex) {
throw new HttpException(ex.getMessage());
}
} else {
target = host;
}
final boolean secure = target.getSchemeName().equalsIgnoreCase("https");
return proxy == null
? new HttpRoute(target, local, secure)
: new HttpRoute(target, local, proxy, secure);
}
/**
* This implementation returns null.
*
* @throws HttpException may be thrown if overridden
*/
protected HttpHost determineProxy(
final HttpHost target,
final HttpRequest request,
final HttpContext context) throws HttpException {
return null;
}
}
DefaultRoutePlanner实现了HttpRoutePlanner接口,其determineRoute方法在host的port小于等于0时通过schemePortResolver.resolve来确定port
SchemePortResolver
org/apache/http/conn/SchemePortResolver.java
/**
* Strategy for default port resolution for protocol schemes.
*
* @since 4.3
*/
public interface SchemePortResolver {
/**
* Returns the actual port for the host based on the protocol scheme.
*/
int resolve(HttpHost host) throws UnsupportedSchemeException;
}
SchemePortResolver接口定义了resolve方法,用于根据协议来返回真正的port
DefaultSchemePortResolver
org/apache/http/impl/conn/DefaultSchemePortResolver.java
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class DefaultSchemePortResolver implements SchemePortResolver {
public static final DefaultSchemePortResolver INSTANCE = new DefaultSchemePortResolver();
@Override
public int resolve(final HttpHost host) throws UnsupportedSchemeException {
Args.notNull(host, "HTTP host");
final int port = host.getPort();
if (port > 0) {
return port;
}
final String name = host.getSchemeName();
if (name.equalsIgnoreCase("http")) {
return 80;
} else if (name.equalsIgnoreCase("https")) {
return 443;
} else {
throw new UnsupportedSchemeException(name + " protocol is not supported");
}
}
}
DefaultSchemePortResolver方法针对http返回80,针对https返回443,其他的抛出UnsupportedSchemeException
小结
HttpClient的HttpRoutePlanner接口定义了determineRoute方法,用于决定该请求的目标route;DefaultRoutePlanner实现了HttpRoutePlanner接口,其determineRoute方法在host的port小于等于0时通过schemePortResolver.resolve来确定port(http返回80,https返回443
)。