URLConnection(一)

1. 简介

URLConnection是一个抽象类,表示指向URL指定资源的活动连接。URLConnection有两个不同但相关的用途。首先,与URL类相比,它对服务器(特别是HTTP服务器)的交互提供了更多控制。URLConnection可以检查服务器发送的首部,并相应地做出响应。它可以设置客户端请求中使用的首部字段,最后URLConnection可以用POST、PUT和其他HTTP请求方法向服务器发回数据。其次URLConnection类是JAVA的协议处理器机制的一部分,这个机制还包括URLStreamHandler类。协议处理器的思想很简单:它们将处理协议的细节与处理特定数据类型分开,提供相应的用户接口,并完成完整的Web浏览器所完成的其他操作。基类java.net.URLConnection是抽象类,要实现一个特定的协议,就要编写一个有奇怪模式的URL,它不会“绝望”地发出一个错误信息,而是会为这个未知协议下载一个协议处理器,用它与服务器通信。java.net包中只有抽象的URLConnection类。具体的子类都隐藏在sun.net包中。URLConnection的许多方法以及一个构造函数都是保护的,意味着它们只能有URLConnection类或其子类实例访问。

2. 打开URLConnection

直接打开URLConnetion类的程序遵循一下基本步骤:

  • 构造一个URL对象
  • 调用这个URL对象的openConnetion()获取对应URL的URLConnetion对象
  • 配置这个URLConnection
  • 读取首部字段
  • 获得输入流并读取数据
  • 获得输出流写入数据
  • 关闭连接

URLConnection类声明为抽象类,不过除了Connect方法,其他方法基本上它本身都已经实现了,所以其子类必须实现connect方法,该方法建立与服务器的连接,因而依赖与服务类型。第一次构造URLConnection时,它是未连接的,也就是说,本地和远程主机无法发送和接受数据。没有Socket连接这两个主机,connect()方法在本地和远程主机之间建立一个连接(一般使用TCP Socket),这样就可以收发数据了。不过我们一般不用显示的调用connect()方法,因为对于getInputStream()、getContent()、getHeaderField()方法和其他要求打开连接的方法,如果连接没有打开,这些方法内部会调用connect()方法

3. 读取服务器的数据

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

  • 构造一个URL对象
  • 调用这个URL对象的openConnection()方法,获取对应URL得URLConnection对象
  • 调用这个URLConnection的getInputStream()方法
  • 使用通常的流API读取输入流

下面使用URLConnection下载百度主页

public class QuizCardBuilder {
    public static void main(String[] args) {
       try{
           //定义URL对象
           URL u=new URL("http://www.baidu.com");
           //获取URLConnection对象
           URLConnection urlConnection=u.openConnection();
           //在try()中写入我们需要自动关闭的资源,后期会帮我们自动关闭
           try (InputStream raw=urlConnection.getInputStream()){
               //以流链的形式封装原始流,加入缓存提高IO效率
               InputStream buffer=new BufferedInputStream(raw);
               Reader reader=new InputStreamReader(buffer);
               int c;
               while((c=reader.read())!=-1){
                   System.out.print((char)c);
               }
           }
       } catch (MalformedURLException e) {
           throw new RuntimeException(e);
       } catch (IOException e) {
           throw new RuntimeException(e);
       }
    }
}

在这里插入图片描述

对于这个例子这样一个简单的输入流,URL和URLConnection之间的区别并不明显

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

4. 读取首部

如下图我们在谷歌浏览器中看到我们请求的头信息,其主要包括六个部分:

  • Content-type:实际返回的内容的内容类型
  • Content-length:实际返回的内容的内容长度
  • Content-encoding:实际返回的内容的内容编码
  • Date:实际返回的内容
  • Last-modified:上一次在服务端的修改时间
  • Expires:头信息过期时间

在这里插入图片描述

下面介绍URLConnection的对应获取方法

  • public String getContentType()

该方法返回响应体的MIME内容类型,它一路web服务器发来的一个有效的内容类型。

public class QuizCardBuilder {
    public static void main(String[] args) {
       try{
           //定义URL对象
           URL u=new URL("http://www.baidu.com");
           //获取URLConnection对象
           URLConnection urlConnection=u.openConnection();
           //在try()中写入我们需要自动关闭的资源,后期会帮我们自动关闭
           System.out.println(urlConnection.getContentType());
       } catch (MalformedURLException e) {
           throw new RuntimeException(e);
       } catch (IOException e) {
           throw new RuntimeException(e);
       }
    }
}

在这里插入图片描述

  • public int getContentLength()

告诉你内容有多少字节,如果没有Content-length首部就会返回-1.如果发现资源的长度超过Integer.MAXVALUE也会返回-1,下面代码实现了下载二进制文件。

public class QuizCardBuilder {
    public static void main(String[] args) {
        try {
            //定义URL对象
            URL u = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fbbe9c79f-2f81-4387-bc64-c88b5daf78fa%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1687610199&t=d3fd58ff3a0f868d2511c8fc1adaecbd");
            URLConnection urlConnection = u.openConnection();
            File mygram = new File("my.jpg");
            saveBinaryFile(u);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void saveBinaryFile(URL u) throws IOException{
    //获得URLConnection对象
        URLConnection urlConnection=u.openConnection();
    //获得Content-type
        String contentype=urlConnection.getContentType();
        System.out.println("Contentype:"+contentype);
    //获得Content-length
        int contetnLength=urlConnection.getContentLength();
        System.out.println("ContentLength:"+contetnLength);
        if(contentype.startsWith("text/")||contetnLength==-1){
            throw new IOException("this is not a binary file");
        }
        //获得内容的IO流
        try(InputStream raw=urlConnection.getInputStream()){
            InputStream in =new BufferedInputStream(raw);
            byte[] data=new byte[contetnLength];
            int offset=0;
            while(offset < contetnLength){
                int bytesRead=in.read(data,offset,data.length-offset);
                if(bytesRead==-1) break;
                offset+=bytesRead;
            }
            try(FileOutputStream fout=new FileOutputStream("myimg.jpg")){
                fout.write(data);
                fout.flush();
            }
        }
    }
}

百度图片的信息
在这里插入图片描述

成功下载到本地
在这里插入图片描述

  • public String getContentEncoding()

该方法返回一个String,指出内容是如何编码的,如果发送的内容没有编码,这个方法就会返回null,而不抛出异常。

  • public long getDate

该方法返回一个long,指出文档何时发送,这个时间按格林乔治标准时间(GMT)

  • public long getExpiration()

有些文档基于服务器的过期时间,指示应当何时从缓存中删除文档,并从服务器重新下载。

  • public long getLastModified()

返回文档的最后修改日期。

5. 获取任意首部字段

上面的6个方法请求首部中的指定字段,不过对于一个消息中包含多少首部字段理论上没有限制,下面5个方法可以检索首部中的任意字段。

  • public String getHeaderField(String name)

该方法返回指定首部字段的值,首部的名称不区分大小写,也不包含结束冒号。

public class QuizCardBuilder {
    public static void main(String[] args) {
        try {
            //定义URL对象
            URL u = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fbbe9c79f-2f81-4387-bc64-c88b5daf78fa%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1687610199&t=d3fd58ff3a0f868d2511c8fc1adaecbd");
            URLConnection urlConnection = u.openConnection();
            System.out.println("ContenType:"+urlConnection.getHeaderField("Content-Type"));
            System.out.println("Date:"+urlConnection.getHeaderField("Date"));
            System.out.println("Last-Modified+"+urlConnection.getHeaderField("Last-Modified"));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

在这里插入图片描述

  • public String getHeaderFieldKey(int n)

这个方法返回第n个首部字段的键。请求方法本身就是第0个首部,它的键是null

public class QuizCardBuilder {
    public static void main(String[] args) {
        try {
            //定义URL对象
            URL u = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fbbe9c79f-2f81-4387-bc64-c88b5daf78fa%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1687610199&t=d3fd58ff3a0f868d2511c8fc1adaecbd");
            URLConnection urlConnection = u.openConnection();
            System.out.println("1:"+urlConnection.getHeaderFieldKey(1));
            System.out.println("2:"+urlConnection.getHeaderFieldKey(2));
            System.out.println("3:"+urlConnection.getHeaderFieldKey(3));
            System.out.println("4:"+urlConnection.getHeaderFieldKey(4));
            System.out.println("5:"+urlConnection.getHeaderFieldKey(5));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

在这里插入图片描述

  • public String getHeaderField(int n)

这个方法是返回第n个首部的值。在HTTP中,包含请求方法和路径的起始行是第0个首部。下面代码来显示所有首部:

public class QuizCardBuilder {
    public static void main(String[] args) {
        try {
            //定义URL对象
            URL u = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fbbe9c79f-2f81-4387-bc64-c88b5daf78fa%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1687610199&t=d3fd58ff3a0f868d2511c8fc1adaecbd");
            URLConnection urlConnection = u.openConnection();
            for (int i = 1; ; i++) {
                String header=urlConnection.getHeaderField(i);
                if(header==null)break;
                System.out.println(urlConnection.getHeaderFieldKey(i)+": "+header);
            }
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

在这里插入图片描述

  • public long getHeaderFieldDate(String name,long default)

这个方法首先获取由name参数指定的首部字段,然后尝试将这个字符转换为一个long(GMT 1970年1月1日子夜之后经过的毫秒数)。它可以用来获取表示日期的首部字段。为了将字符串转换为整数,该方法使用了java.util.Date中的parseDate方法

public class QuizCardBuilder {
    public static void main(String[] args) {
        try {
            //定义URL对象
            URL u = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fbbe9c79f-2f81-4387-bc64-c88b5daf78fa%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1687610199&t=d3fd58ff3a0f868d2511c8fc1adaecbd");
            URLConnection urlConnection = u.openConnection();
            System.out.println(urlConnection.getHeaderFieldDate("Expires",0));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

在这里插入图片描述

  • public int getHeaderField(String name,int default)

这个方法获取首部字段name的值,尝试将其转换为int。

public class QuizCardBuilder {
    public static void main(String[] args) {
        try {
            //定义URL对象
            URL u = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fbbe9c79f-2f81-4387-bc64-c88b5daf78fa%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1687610199&t=d3fd58ff3a0f868d2511c8fc1adaecbd");
            URLConnection urlConnection = u.openConnection();
            System.out.println(urlConnection.getHeaderFieldInt("content-length",-1));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值