HttpURLConnection对象的获取

来源:互联网 发布:人工智能在制造业应用 编辑:程序博客网 时间:2024/06/06 02:57

1,获取HttpURLConnection对象

获取HttpURLConnection对象有不同的方法.

以下分析都是基于android 6.0

1,通过URL对象获取,

getUrl = new URL("http://•••/");mSocketAddress = new InetSocketAddress(•••,mProxyPort);Proxy proxy = new Proxy(Proxy.Type.HTTP,mSocketAddress);conn = (HttpURLConnection) getUrl.openConnection(proxy);

2,通过Network对象获取,

getUrl = new URL("http://•••/");mSocketAddress = new InetSocketAddress(•••,mProxyPort);Proxy proxy = new Proxy(Proxy.Type.HTTP,mSocketAddress);conn = (HttpURLConnection) mNetwork.openConnection(getUrl,proxy);

1.1通过URL对象获取

1.1.1 URL对象构造

URL有6个构造方法,仅有一个String参数的构造方法如下,

public URL(String spec) throws MalformedURLException {   this((URL) null, spec, null);}

三个参数的URL构造方法主要逻辑如下,

1,调用setupStreamHandler方法获取URLStreamHandler对象,

if (streamHandler == null) {    setupStreamHandler();    if (streamHandler == null) {         throw new MalformedURLException("Unknown protocol: " + protocol);    }}

2,调用URLStreamHandler对象的parseURL方法解析网址,

try {   streamHandler.parseURL(this, spec, schemeSpecificPartStart, spec.length());} catch (Exception e) {   throw new MalformedURLException(e.toString());}

setupStreamHandler的主要逻辑如下,

1,如果streamHandlers Hashtable里面已经保存了就直接从里面取出来就可以了,

streamHandler = streamHandlers.get(protocol);if (streamHandler != null) {    return;}

一般一个网址对应一个URLStreamHandler对象。

2,如果URLStreamHandlerFactory对象不为空就可以利用URLStreamHandlerFactory创建URLStreamHandler对象,

if (streamHandlerFactory != null) {    streamHandler = streamHandlerFactory.createURLStreamHandler(protocol);    if (streamHandler != null) {        streamHandlers.put(protocol, streamHandler);        return;    }}

当然,可以并且只能通过setURLStreamHandlerFactory方法设置URLStreamHandlerFactory对象。

3,如果系统内已经有可以加载URLStreamHandler的包,就优先使用系统的包加载,

String packageList = System.getProperty("java.protocol.handler.pkgs");ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();if (packageList != null && contextClassLoader != null) {    for (String packageName : packageList.split("\\|")) {         String className = packageName + "." + protocol + ".Handler";         try {            Class<?> c = contextClassLoader.loadClass(className);            streamHandler = (URLStreamHandler) c.newInstance();            if (streamHandler != null) {                 streamHandlers.put(protocol, streamHandler);            }            return;            } catch (IllegalAccessException ignored) {            } catch (InstantiationException ignored) {            } catch (ClassNotFoundException ignored) {         }    }}

4,最后根据网址的类型分别构造对应的URLStreamHandler对象.

if (protocol.equals("file")) {     streamHandler = new FileHandler();} else if (protocol.equals("ftp")) {     streamHandler = new FtpHandler();} else if (protocol.equals("http")) {    try {       String name = "com.android.okhttp.HttpHandler";       streamHandler = (URLStreamHandler) Class.forName(name).newInstance();    } catch (Exception e) {      throw new AssertionError(e);    }} else if (protocol.equals("https")) {   try {      String name = "com.android.okhttp.HttpsHandler";      streamHandler = (URLStreamHandler) Class.forName(name).newInstance();   } catch (Exception e) {       throw new AssertionError(e);}•••

URLStreamHandler其实是一个抽象类,具体的由各个子类实现。在此,根据不同的请求获取不同的URLStreamHandler子类。

http格式的网址对应的是HttpHandler类。

1.1.2 HttpURLConnection对象

通过URL对象获取HttpURLConnection对象的openConnection方法也有2个,其实就是有没有指定代理(特定APN)的区别,

有代理的openConnection调用流程图如下,


URL的openConnection方法如下,

public URLConnection openConnection(Proxy proxy) throws IOException {   if (proxy == null) {        throw new IllegalArgumentException("proxy == null");   }   return streamHandler.openConnection(this, proxy);}

streamHandler就是在上个小节中获取的URLStreamHandler对象,

对于http格式的网址,对应的是URLStreamHandler的子类HttpHandler。

HttpHandler的openConnection方法如下,

protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {  if (url == null || proxy == null) {       throw new IllegalArgumentException("url == null || proxy == null");  }  return newOkUrlFactory(proxy).open(url);}

该方法首先调用newOkUrlFactory方法构造OkUrlFactory对象,然后调用其open方法。newOkUrlFactory方法逻辑如下,

protected OkUrlFactory newOkUrlFactory(Proxy proxy) {   OkUrlFactory okUrlFactory = createHttpOkUrlFactory(proxy);   •••   okUrlFactory.client().setConnectionPool(configAwareConnectionPool.get());   return okUrlFactory;}

createHttpOkUrlFactory方法主要逻辑如下,

1,构造OkHttpClient对象,

OkHttpClient client = new OkHttpClient();

2,利用OkHttpClient对象设置代理,

if (proxy != null) {    client.setProxy(proxy);}

3,利用OkHttpClient对象构造OkUrlFactory对象,

OkUrlFactory okUrlFactory = new OkUrlFactory(client);

OkUrlFactory的open方法如下,

public HttpURLConnection open(URL url) {   return open(url, client.getProxy());}

Open方法也会根据网址构造不同的HttpURLConnection代理对象,

HttpURLConnection open(URL url, Proxy proxy) {    String protocol = url.getProtocol();    OkHttpClient copy = client.copyWithDefaults();    copy.setProxy(proxy);    if (protocol.equals("http")) return new HttpURLConnectionImpl(url, copy);    if (protocol.equals("https")) return new HttpsURLConnectionImpl(url, copy);    throw new IllegalArgumentException("Unexpected protocol: " + protocol);}

以http请求为例,通过URLConnection的openConnection方法最后获取的HttpURLConnection对象

其实是代理HttpURLConnectionImpl对象。

1.2通过Network对象获取

Network的openConnection方法逻辑如下,

1,利用请求网址调用HttpHandler的createHttpOkUrlFactory方法构造OkUrlFactory对象,

if (protocol.equals("http")) {    okUrlFactory = HttpHandler.createHttpOkUrlFactory(proxy);} else if (protocol.equals("https")) {    okUrlFactory = HttpsHandler.createHttpsOkUrlFactory(proxy);}

HttpHandler的createHttpOkUrlFactory方法在上个小节已经论述了,此就不赘述了。

2,调用OkUrlFactory对象的open方法创建HttpURLConnectionImpl对象。

return okUrlFactory.open(url);

由此可见,这2中方法最后都会调用OkUrlFactory对象的open方法创建HttpURLConnectionImpl对象,实质完全相同。

原创粉丝点击