美文网首页Java
URLConnection

URLConnection

作者: 随风_d6a2 | 来源:发表于2021-02-24 22:11 被阅读0次

    简介

    URLConnection是一个抽象类,表示指向URL指定资源的活动连接。URLConnection有两个不同但相关的用途:

    • URLConnection可以检查服务器发送的首部,并相应地做出响应。它可以设置客户端请求中使用的首部字段。最后URLConnection可以用POST、PUT和其他HTTP请求方法向服务器发回数据;
    • URLConnection类是Java的协议处理器机制的一部分;

    打开URLConnection

    直接使用URLConnection类的程序遵循以下基本步骤:

    1. 构造一个URL对象;
    2. 调用这个URL对象的openConnection()获取一个对应该URL的URLConnection对象;
    3. 配置这个URLConnection;
    4. 读取首部字段;
    5. 获得输入流并读取数据;
    6. 获得输出流并写入数据;
    7. 关闭连接;

    并不一定执行所有这些步骤。看你需不需要!
    URLConnection类仅有的一个构造函数为保护类型:

    protected URLConnection(URL url)
    
    
    try {
                URL url = new URL("http://www.baidu.com");
                URLConnection connection = url.openConnection();
                //从URL读取。。。
            } catch (Exception e) {
                // TODO: handle exception
            }
    
    

    读取服务器的数据

    下面是使用URLConnection对象从一个URL获取数据所需的最起码的步骤:

    1. 构造一个URL对象;
    2. 调用这个URL对象的openConnection()方法,获取对应该该URL的URLConnection对象;
    3. 调用这个URLConnection的getInputStream()方法;
    4. 使用通常的流API读取输入流;

    getInputStream()方法返回一个通用InputStream,可以读取和解析服务器发送的数据:

    public class Test {
    
        public static void main(String[] args) {
            try {
                //打开URLConnection进行读取
                URL url = new URL("http://www.baidu.com");
                URLConnection connection = url.openConnection();
                try (InputStream in = connection.getInputStream()){    //带资源的try-catch语句。自动关闭
                    InputStream buffer = new BufferedInputStream(in);
                    //将InputStream串链到一个Reader
                    Reader reader = new InputStreamReader(buffer);
                    int c;
                    while ((c = reader.read())!= -1) {
                        System.out.print((char)c);
                    }
                } catch (MalformedURLException e) {
    
                }
            } catch (IOException e) {
    
            }
        }   
    }
    
    

    运行:


    在这里插入图片描述

    URL和URLConnection这两个类最大的不同在于:

    • URLConnection提供了对HTTP首部的访问;
    • URLConnection可以配置发送给服务器的请求参数;
    • URLConnection除了读取服务器数据外,还可以向服务器写入数据;

    读取指定的首部字段

    前6个方法可以请求首部中特定的常用字段:

    • Content-Type
    • Content-Length
    • Content-encoding
    • Date
    • Last-modified
    • Expires

    public String getContentType()
    getContentType()方法返回响应主体的MIME内容类型。如果没有提供内容类型,它不会抛出异常,而是返回null;

    public int getContentLength()
    getContentLength()方法告诉你内容中有多少字节。如果没有Content-Length首部,getContentLength()就返回-1;

    public long getContentLengthLong()--------Java7增加的
    与getContentLength()类似,只不过它会返回一个long而不是int,这样就可以处理更大的资源;

    public String getContentEncoding()
    getContentEncoding()方法返回一个String,指出内容是如何编码的。如果发送的内容没有编码,这个方法就返回null;

    public long getDate()
    getDate()方法返回一个long,指出文档何时发送;

    public long getExpiration()
    有些文档有基于服务器的过期日期,指示应当何时从缓存中删除文档,并从服务器重新下载。如果HTTP首部没有包括Expiration字段,getExpiration()就返回0,这表示文档不会过期,将永远保留在缓存中;

    public long getLastModified()
    返回文档的最后修改日期;
    Test .java

    public class Test {
    
        public static void main(String[] args) {
            try {
                URL url = new URL("http://www.baidu.com");
                URLConnection connection = url.openConnection();
                System.out.println("Content-Type: " + connection.getContentType());
                System.out.println("Content-Length: " + connection.getContentLength());
                System.out.println("Content-LengthLong: " + connection.getContentLengthLong());
                System.out.println("Content-encoding: " + connection.getContentEncoding());
                System.out.println("Date: " + connection.getDate());
                System.out.println("Expires: " + connection.getExpiration());
                System.out.println("Last-modified: " + connection.getLastModified());
            } catch (IOException e) {
    
            }
        }   
    }
    
    
    在这里插入图片描述

    获取任意首部字段

    public String getHeaderField(String name)
    getHeaderField()方法返回指定首部字段的值。首部的名不区分大小写,也不包含结束冒号;

    URL url = new URL("http://www.baidu.com");
    URLConnection connection = url.openConnection();
    System.out.println(connection.getHeaderField("Content-Type"));
    System.out.println(connection.getHeaderField("last-modified"));
    
    //输出
    text/html
    Mon, 23 Jan 2017 13:27:36 GMT
    
    

    public String getHeaderFieldKey(int n)
    返回第n个首部字段的键(即字段名)。请求方法本身是第0个首部,它的键为null。第一个首部即编号为1:

    System.out.println(connection.getHeaderFieldKey(5));    //输出Content-Type
    
    

    public String getHeaderField(int n)
    返回第n个首部字段的值,包含请求方法和路径的起始行是第0个首部字段,实际的第一个首部编号为1:
    Test.java–循环显示整个HTTP首部

    public class Test {
    
        public static void main(String[] args) {
            try {
                URL url = new URL("http://www.baidu.com");
                URLConnection connection = url.openConnection();
                for (int i = 1; ; i++) {
                    String header = connection.getHeaderField(i);
                    if (header == null) {
                        break;
                    }
                System.out.println(connection.getHeaderFieldKey(i)+": "+header);    
                }
            } catch (IOException e) {
    
            }
        }   
    }
    
    //输出
    Accept-Ranges: bytes
    Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
    Connection: Keep-Alive
    Content-Length: 2381
    Content-Type: text/html
    Date: Thu, 04 Oct 2018 13:14:20 GMT
    Etag: "588604ec-94d"
    Last-Modified: Mon, 23 Jan 2017 13:28:12 GMT
    Pragma: no-cache
    Server: bfe/1.0.8.18
    Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
    
    

    public long getHeaderFieldDate(String name, long Default)
    这个方法首先获取由name参数指定的首部字段,然后尝试将这个字符串转换为一个long;

    public long getHeaderFieldInt(String name, int Default)
    这个方法获取首部字段name的值,尝试将其转换为int;

    缓存

    默认情况下,一般认为使用GET通过HTTP访问的页面可以缓存,也应当缓存。使用HTTPS或POST访问的页面通常不应缓存。不过,HTTP首部可以对此做出调整:


    在这里插入图片描述
    • Last-modified首部指示资源最后一次修改的日期。客户端可以使用一个HEAD请求来检查这个日期,只有当本地缓存的副本早于Last-modified日期时,它才会真正执行GET来获取资源;
    在这里插入图片描述

    Java的Web缓存

    。。。用到再写;

    配置连接

    URLConnection类有7个保护的实例字段,定义了客户端如何向服务器做出请求:

    protected URL url;
    protected boolean doInput = true;
    protected boolean doOutput = false;
    protected boolean allowUserInteraction = defaultAllowUserInteraction;
    protected boolean useCaches = defaultUseCaches;
    protected long ifModifiedSince = 0;
    protected boolean connected = false;
    
    

    例如,如果doOutput为true,那么除了通过这个URLConnection读取数据外,还可以将数据写入到服务器。如果useCaches为false,连接会绕过所有本地缓存,重新从服务器下载文件;

    由于这些字段都是保护字段,所以它们的值要通过相应的set方法和get方法来访问和修改!
    只能在URLConnection连接之前修改这些字段,对于设置字段的方法,如果调用这些方法时连接已经打开,大多数方法会抛出一个IllegalStateException异常!

    protected URL url
    url字段指定了这个URLConnection连接的URL。可以通过getURL()方法获取这个字段的值

    public class Test {
    
        public static void main(String[] args) {
            try {
                URL url = new URL("http://www.baidu.com");
                URLConnection connection = url.openConnection();
                System.out.println(connection.getURL());         //输出http://www.baidu.com
            } catch (IOException e) {           
            }
        }   
    }
    
    

    protected boolean connected
    如果连接已经打开,boolean字段connected为true,如果连接关闭,这个字段则为false。由于创建一个新的URLConnection对象时连接尚未打开,所以其初始值为false。没有直接读取或改变connected值的方法。不过,任何导致URLConnection连接的方法都会将这个变量设置为true;

    protected boolean allowUserInteraction
    有些URLConnection需要与用户交互。allowUserInteraction字段指示了是否允许用户交互。默认值为false;

    protected boolean doInput
    URLConnection可以用于读取服务器、写入服务器,或者同时用于读/写服务器。如果URLConnection可以用来读取,保护类型boolen字段doInput就为true,否则为false;默认为true!

    protected boolean doOutput
    如果URLConnection可以用于写入,保护类型boolen字段doOutput就为true,否则为false;默认为false!

    protected long ifModifiedSince

    在这里插入图片描述

    protected boolean useCaches
    useCaches变量确定了是否可以使用缓存。默认值为true,表示将使用缓存;false表示不使用缓存 !!

    超时

    有4个方法可以查询和修改连接的超时值。也就是说,底层socket等待远程服务器的响应时,等待多长时间后会抛出SocketTimeoutException异常:

    //控制socket等待建立连接的时间
    public void setConnectTimeout(int timeout)
    public int getConnectTimeout()
    
    //控制输入流等待数据到达的时间
    public void setReadTimeout(int timeout)
    public int getReadTimeout()
    
    

    都以毫秒为单位。都将0解释为永远不超时。如果超时值为负数,两个设置方法都会抛出IllegalArgumentException异常;

    配置客户端请求HTTP首部

    每个URLConnection会在首部默认设置一些不同的名–值对。打开连接前,可以使用setRequestProperty()方法为HTTP首部增加首部字段:

    //只能在连接打开之前使用。如果连接已经打开,它将抛出一个IllegalArgumentException异常;getRequestProperty()方法返回这个
    //URLConnection所用HTTP首部中指定字段的值
    public void setRequestProperty(String key, String value)
    
    

    HTTP允许一个指定名字的属性有多个值。在这种情况下,各个值用逗号隔开;
    要增加另外一个属性值,需要使用addRequestProperty()方法:

    public void addRequestProperty(String key, String value)
    
    

    如果出于某种原因需要查看URLConnection中的首部,有一个标准的获取方法:

    public String getRequestProperty(String key)
    
    

    Java还提供了一个方法,可以获得连接的所有请求属性并作为一个Map返回:

    public Map<String,List<String>> getRequestProperties()  //键是首部名,值是属性值列表
    
    

    向服务器写入数据

    有时你需要向URLConnection写入数据,例如,使用POST向Web服务器提交表单,或者使用PUT上传文件。
    getOutputStream()方法返回一个OutputStream,可以用来写入数据传送给服务器:

    public OutputStream getOutputStream()
    
    

    由于URLConnection在默认的情况下不允许输出,所以在请求输出流之前必须调用setDoOutput(true)。为一个HTTP URL将doOutput设置为true时,请求方法将由GET变为POST;

    public static void main(String[] args) {
            try {
                URL url = new URL("http://www.baidu.com");          
                URLConnection connection = url.openConnection();
                connection.setDoOutput(true);
                OutputStream out = connection.getOutputStream();
                OutputStream buff = new BufferedOutputStream(out);
                OutputStreamWriter writer = new OutputStreamWriter(buff);
                writer.write("name=yd&sex=man");
                writer.flush();
                writer.close();
            } catch (IOException e) {
    
            }
        }   
    
    
    在这里插入图片描述

    HttpURLConnection

    java.net.HttpURLConnection类是URLConnection的抽象子类。它提供了另外一些方法,在处理http URL时尤其有帮助;
    由于这个类是抽象类,唯一的构造函数是保护类型的,所以不能直接创建HttpURLConnection的实例:

    URL url = new URL("http://www.baidu.com");
    URLConnection connection = url.openConnection();
    HttpURLConnection http =  (HttpURLConnection) connection;
    
    

    或者可以跳过一个步骤:

    URL url = new URL("http://www.baidu.com");  
    HttpURLConnection http =  (HttpURLConnection) url.openConnection();
    
    

    请求方法

    在这里插入图片描述

    默认情况下,HttpURLConnection会使用GET方法。不过,可以用setRequestMethod()来改变请求方法:

    public void setRequestMethod(String method) throws ProtocolException
    
    

    这个方法的参数应当是以下7个字符之一:

    • GET:
    • POST
    • HEAD:HEAD与GET相似。不过,它告诉服务器只返回HTTP首部;这个方法最常用的用途是检查文件在最后一次缓存之后是否有修改;
    • PUT:这个方法允许客户端将文档放在网站的抽象层次结构中,而不需要知道网站如何映射到实际的本地文件系统;
    • DELETE:DELETE方法将删除Web服务器上位于指定URL的文件;
    • OPTIONS:OPTIONS请求方法询问某个特定URL支持哪些选项。如果请求的URL是星号(*),那么这个请求将应用于整个服务器而不是服务器上的某个URL;
    • TRACE:TRACE请求方法会发送HTTP首部,服务器将从客户端接收这个HTTP首部;

    如果使用其他方法,就会抛出java.net.ProtocolException异常,这是IOException的一个子类;

    断开与服务器的连接

    HTTP1.1支持持久连接,允许通过一个TCP socket发送多个请求和响应。HttpURLConnection类透明地支持HTTP Keep-Alive,除非显式将其关闭。一旦知道与一个特定主机的会话结束,disconnect()方法允许客户端断开连接:

    public abstract void disconnect()
    
    

    如果这个连接上还有打开的流,disconnect()将关闭这些流。不过,反过来并不成立。关闭一个持久连接上的流时,并不会关闭这个socket并断开连接;

    处理服务器响应

    通常响应消息中我们只需要数字响应码。HttpURLConnection有一个getResponseCode()方法,会以int返回这个响应码:

    public int getResponseCode() throws IOException
    
    

    响应码后面的文本字符串称为响应信息。可以由一个getResponseMessage()方法返回:

    public String getResponseMessage() throws IOException
    
    

    重定向
    默认情况下,HttpURLConnection会跟随重定向。不过,HttpURLConnection有两个静态方法,允许你确定是否跟随重定向:

    public static boolean getFollowRedirects()
    public static void setFollowRedirects(boolean set)
    
    

    如果跟随重定向,getFollowRedirects()方法就会返回true,否则返回false。当参数为true时,setFollowRedirects()会让HttpURLConnection对象跟随重定向。当参数为false,则会阻止HttpURLConnection对象跟随重定向。
    代理
    usingProxy()方法可以指定某个HttpURLConnection是否通过代理服务器:

    public abstract boolean usingProxy()
    

    相关文章

      网友评论

        本文标题:URLConnection

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