美文网首页
URLConnection

URLConnection

作者: 麦崎 | 来源:发表于2020-10-12 14:00 被阅读0次

    概念

    URI(Uniform Resource Identifier)

    • URI是互联网上标识某一资源的字符串,是一个抽象的概念。
    • URI通常由三部分组成:资源的命名机制;存放资源的主机名;资源自身的名称。

    URL(uniform resource locator)

    • URL是互联网上描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,URL是URI概念的一种实现方式,提供了定位资源的具体方式。
    • URL的一般格式为(带方括号[]的为可选项):
      protocol :// hostname[:port] / path / [;parameters][?query]#fragment
    • URL的格式由三部分组成:
      1.协议(或称为服务方式);
      2.存有该资源的主机IP地址(有时也包括端口号);
      3.主机资源的具体地址,如目录和文件名等;
      其中,第一部分和第二部分用“://”符号隔开,第二部分和第三部分用“/”符号隔开,第一部分和第二部分是不可缺少的,第三部分有时可以省略。

    URLConnection

    https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html
    URLConnection抽象类为应用程序提供了访问URL的方式,其示例提供了读写URL资源的方法。

    HTTPURLConnection

    https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html
    HTTPURLConnection是提供了对HTTP协议支持的URLConnection。

    示例

    import java.io.*;
    import java.net.URL;
    import java.net.URLConnection;
    
    public class GreetingURLConn {
    
    
        public static void main(String[] args) {
            testRead();
        }
    
        private static void testRead() {
            InputStream input = null;
            try {
                // 连接
                URL url = new URL("http://www.baidu.com");
                URLConnection connection = url.openConnection();
    
                // 读取
                input = connection.getInputStream();
                InputStream raw = new BufferedInputStream(input);
                Reader r = new InputStreamReader(raw);
                StringBuffer result = new StringBuffer();
                int c;
                while ((c = r.read()) > 0) {
                    result.append((char) c);
                }
    
                System.out.println(result);
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (input != null) {
                        input.close();
                    }
                } catch (IOException ignore) {
                }
            }
        }
    }
    

    源码分析

    Url.openConnection

    1. 调用URLStreamHandler的 openConnection, 不同的协议有不同的URLStreamHandler
    2. 以HTTP协议的Handler为例,openConnection其实就是构建一个HttpURLConnection实例
    package sun.net.www.protocol.http;
    ...
    public class Handler extends URLStreamHandler{
        ...
        protected URLConnection openConnection(URL var1, Proxy var2) throws   IOException {
             return new HttpURLConnection(var1, var2, this);
        }
    }
    

    HttpURLConnection.getInputStream

     private synchronized InputStream getInputStream0() throws IOException {
            if (...) { // 异常检查
              ...
            } else if (this.inputStream != null) { // 缓存
                return this.inputStream;
            } else {
                // 如果正在写入,先处理写入
                if (this.streaming()) {
                    if (this.strOutputStream == null) {
                        this.getOutputStream();
                    }
    
                    this.strOutputStream.close();
                    if (!this.strOutputStream.writtenOK()) {
                        throw new IOException("Incomplete output stream");
                    }
                }
    
               ...
    
                InputStream var45;
                try {
                    int var33;
                    while(true) {
                        if (!this.checkReuseConnection()) {
                            // 这里会构建HttpClient,存储为成员变量http
                            // HttpClient有缓存机制
                            // 构建HttpClient的时候,会创建socket实例,并获得输出通道存道,存储为HttpClient的成员变量serverOutput
                            this.connect();
                        } 
                        ...
                        this.ps = (PrintStream)this.http.getOutputStream();
                        if (!this.streaming()) {
                           // 构建request,通过HttpClient写入serverOutput,具体见下方
                            this.writeRequests();
                        }
                        // 通过HttpClient获得输入通道,存储为HttpClient的成员变量serverInput,并初步解析到MessageHeader类型的实例responses中
                        this.http.parseHTTP(this.responses, this.pi, this);
                        ...
                        this.inputStream = this.http.getInputStream();
                        // 获取responseCode并做一些异常处理
                        var33 = this.getResponseCode();
                        if (var33 == -1) {
                            this.disconnectInternal();
                            throw new IOException("Invalid Http response");
                        }
                       ...
                            if (var33 == 200) {
                                this.checkResponseCredentials(false);
                            } else {
                                this.needToCheck = false;
                            }
                            this.needToCheck = true;
                          
                       ...
    
                    }
    
                    
    
                return var45;
            }
        }
    

    writeRequests

     private void writeRequests() throws IOException {
            if (this.http.usingProxy && this.tunnelState() != HttpURLConnection.TunnelState.TUNNELING) {
                this.setPreemptiveProxyAuthentication(this.requests);
            }
    
            if (!this.setRequests) {
               // 各种公共Header处理 ,如 "Content-type"      
               ... 
                if (!this.method.equals("PUT") && (this.poster != null || this.streaming())) 
               {
                    this.requests.setIfNotSet("Content-type", "application/x-www-form-urlencoded");
                }
    
                this.setCookieHeader();
                this.setRequests = true;
            }
            // 在HTTPClient中写入请求流
            this.http.writeRequests(this.requests, this.poster, this.streaming());
            if (this.ps.checkError()) {  // IO异常,重新处理一次请求
                ...
                if (this.failedOnce) {
                    throw new IOException("Error writing to server");
                }
    
                this.failedOnce = true;
                // 重置一些参数和http实例,略
                ...
                this.writeRequests();
            }
    
        }
    

    相关文章

      网友评论

          本文标题:URLConnection

          本文链接:https://www.haomeiwen.com/subject/dsodpktx.html