-
本文概述
从源码角度理解HttpURLConnection是怎么一步步封装底层socket调用的。
-
HttpURLConnection使用回顾
我们先来回顾一下它的用法:
new Thread(() -> { HttpURLConnection connection = null; BufferedReader reader = null; try{ URL url = new URL("https://www.baidu.com");//新建URL connection = (HttpURLConnection)url.openConnection();//发起网络请求 connection.setRequestMethod("GET");//请求方式 connection.setConnectTimeout(8000);//连接最大时间 connection.setReadTimeout(8000);//读取最大时间 InputStream in = connection.getInputStream(); reader = new BufferedReader(new InputStreamReader(in));//写入reader StringBuilder response = new StringBuilder(); String line; while((line = reader.readLine()) != null){ response.append(line); } //更新ui showResponse(response.toString()); }catch (Exception e){ e.printStackTrace(); }finally { if(reader != null){ try{ reader.close(); }catch (IOException e){ e.printStackTrace(); } } if(connection != null){ connection.disconnect(); } } }).start();
接下来从源码角度研究一下它的原理。
-
源码分析
首先构造一个URL对象,然后调用它的openConnection(),进去发现调用的是handler.openConnection(URL url),handler是怎么创建的呢?看一下URL对象的构造方法就会发现一些线索,构造方法最终会走到this(context, spec, null):
public URL(URL context, String spec, URLStreamHandler handler) throws MalformedURLException { String original = spec; int i, limit, c; int start = 0; String newProtocol = null; boolean aRef=false; boolean isRelative = false; // Check for permission to specify a handler if (handler != null) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkSpecifyHandler(sm); } } try { limit = spec.length(); while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { limit--; //eliminate trailing whitespace } while ((start < limit) && (spec.charAt(start) <= ' ')) { start++; // eliminate leading whitespace } if (spec.regionMatches(true, start, "url:", 0, 4)) { start += 4; } if (start < spec.length() && spec.charAt(start) == '#') { /* we're assuming this is a ref relative to the context URL. * This means protocols cannot start w/ '#', but we must parse * ref URL's like: "hello:there" w/ a ':' in them. */ aRef=true; } for (i = start ; !aRef && (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) { if (c == ':') { String s = spec.substring(start, i).toLowerCase(); if (isValidProtocol(s)) { newProtocol = s; start = i + 1; } break; } } // Only use our context if the protocols match. protocol = newProtocol; if ((context != null) && ((newProtocol == null) || newProtocol.equalsIgnoreCase(context.protocol))) { // inherit the protocol handler from the context // if not specified to the constructor if (handler == null) { handler = context.handler; } // If the context is a hierarchical URL scheme and the spec // contains a matching scheme then maintain backwards // compatibility and treat it as if the spec didn't contain // the scheme; see 5.2.3 of RFC2396 if (context.path != null && context.path.startsWith("/")) newProtocol = null; if (newProtocol == null) { protocol = context.protocol; authority = context.authority; userInfo = context.userInfo; host = context.host; port = context.port; file = context.file; path = context.path; isRelative = true; } } if (protocol == null) { throw new MalformedURLException("no protocol: "+original); } // Get the protocol handler if not specified or the protocol // of the context could not be used if (handler
HttpURLConnection源码分析
最新推荐文章于 2020-12-14 09:53:06 发布