精华内容
下载资源
问答
  • 因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、     //  重新发送数据(至于是否不用重新这些操作需要再研究)     objOutputStm.writeObject( new   String( "" ));...
    1. Java中可以使用HttpURLConnection来请求WEB资源。  
    2.   
    3.    
    4.   
    5. 1、 URL请求的类别   
    6.   
    7. 分为二类,GET与POST请求。二者的区别在于:  
    8.       a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,  
    9.       b:) post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。   
    10.   
    11.  
    12. 2、URLConnection的对象问题
    1.  
    2. URL url new URL("http://localhost:8080/TestHttpURLConnectionPro.do");  
    3.   
    4. URLConnection rulConnection url.openConnection();// 此处的urlConnection对象实际上是根据URL的  
    5.           // 请求协议(此处是http)生成的URLConnection类  
    6.           // 的子类HttpURLConnection,故此处最好将其转化  
    7.           // 为HttpURLConnection类型的对象,以便用到  
    8.           // HttpURLConnection更多的API.如下:  
    9.   
    10. HttpURLConnection httpUrlConnection (HttpURLConnection) rulConnection;

    11.  
    12. 3、HttpURLConnection对象参数问题 
    13.  
    14. Java代码      
    15. // 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在  
    16. // http正文内,因此需要设为true, 默认情况下是false;  
    17. httpUrlConnection.setDoOutput(true);  
    18.   
    19. // 设置是否从httpUrlConnection读入,默认情况下是true;  
    20. httpUrlConnection.setDoInput(true);  
    21.   
    22. // Post 请求不能使用缓存  
    23. httpUrlConnection.setUseCaches(false);  
    24.   
    25. // 设定传送的内容类型是可序列化的java对象  
    26. // (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)  
    27. httpUrlConnection.setRequestProperty("Content-type""application/x-java-serialized-object");  
    28.   
    29. // 设定请求的方法为"POST",默认是GET  
    30. httpUrlConnection.setRequestMethod("POST");  
    31.   
    32. // 连接,从上述第2条中url.openConnection()至此的配置必须要在connect之前完成,  
    33.         httpUrlConnection.connect();   
    34.   
    35. 4、HttpURLConnection连接问题  
    36.   
    37. Java代码      
    38. // 此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,  
    39. // 所以在开发中不调用上述的connect()也可以)。  
    40. OutputStream outStrm httpUrlConnection.getOutputStream();   
    41.   
    42. 5、HttpURLConnection写数据与发送数据问题  
    43.   
    44. Java代码   
    45. // 现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。  
    46. ObjectOutputStream objOutputStrm new ObjectOutputStream(outStrm);  
    47.   
    48. // 向对象输出流写出数据,这些数据将存到内存缓冲区中  
    49. objOutputStrm.writeObject(new String("我是测试数据"));  
    50.   
    51. // 刷新对象输出流,将任何字节都写入潜在的流中(些处为ObjectOutputStream)  
    52. objOutputStm.flush();  
    53.   
    54. // 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中,  
    55. // 在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器  
    56. objOutputStm.close();  
    57.   
    58. // 调用HttpURLConnection连接对象的getInputStream()函数,  
    59. // 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。  
    60. InputStream inStrm httpConn.getInputStream(); // <===注意,实际发送请求的代码段就在这里  
    61.   
    62. // 上边的httpConn.getInputStream()方法已调用,本次HTTP请求已结束,下边向对象输出流的输出已无意义,  
    63. // 既使对象输出流没有调用close()方法,下边的操作也不会向对象输出流写入任何数据.  
    64. // 因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、  
    65. // 重新发送数据(至于是否不用重新这些操作需要再研究)  
    66. objOutputStm.writeObject(new String(""));  
    67. httpConn.getInputStream();   
    68.   
    69. 6、post参数的方法  
    70.   
    71. Java代码     
    72. OutputStream os httpConn.getOutputStream();  
    73.             String param new String();  
    74.             param "CorpID=" CorpID  
    75.                     "&LoginName=" LoginName+  
    76.                     "&send_no=" phoneNumber  
    77.                     "&msg=" java.net.URLEncoder.encode(msg,"GBK");  
    78.             os.write(param.getBytes());   
    79.   
    80. 7、超时设置,防止 网络异常的情况下,可能会导致程序僵死而不继续往下执行   
    81.   
    82. Java代码   
    83. System.setProperty("sun.net.client.defaultConnectTimeout""30000");  
    84. System.setProperty("sun.net.client.defaultReadTimeout""30000");  
    85.   
    86. 其中: sun.net.client.defaultConnectTimeout:连接主机的超时时间(单位:毫秒)  
    87. sun.net.client.defaultReadTimeout:从主机读取数据的超时时间(单位:毫秒)  
    88.   
    89. JDK 1.5以前的版本,只能通过设置这两个系统属性来控制网络超时。在1.5中,还可以使用HttpURLConnection的父类URLConnection的以下两个方法:  
    90. setConnectTimeout:设置连接主机超时(单位:毫秒)  
    91. setReadTimeout:设置从主机读取数据超时(单位:毫秒)  
    92.   
    93. 例如:  
    94. HttpURLConnection urlCon (HttpURLConnection)url.openConnection();  
    95. urlCon.setConnectTimeout(30000);  
    96. urlCon.setReadTimeout(30000);   
    97.   
    98.   
    99.   
    100. 总结:   
    101.   
    102.   
    103. a: HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。  
    104.     无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。  
    105.  b:在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,  
    106.     对connection对象的一切配置(那一堆set函数)  
    107.     都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。  
    108.     这些顺序实际上是由http请求的格式决定的。  
    109.     如果inputStream读操作在outputStream的写操作之前,会抛出例外:  
    110.     java.net.ProtocolException: Cannot write output after reading input.......        
    111.  c:http请求实际上由两部分组成,一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文       content。connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前, 
    112.     就必须把所有的配置准备好。  
    113.  d: 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,  
    114.     实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,  
    115.     而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。  
    116.     至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求  
    117.     正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http  
    118.     请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数  
    119.     之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)  
    120.     都是没有意义的了,执行这些操作会导致异常的发生。

    展开全文
  • 2、URLConnection的对象问题 Java代码 URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro.do"); URLConnection rulConnection = url.openConnection();// 此处的urlConnection对象实际上是...
    Java中可以使用HttpURLConnection来请求WEB资源。
     
    1、 URL请求的类别
    分为二类,GET与POST请求。二者的区别在于:
          a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
          b:) post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
     
    2、URLConnection的对象问题
    Java代码  
    URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro.do");  
      
    URLConnection rulConnection = url.openConnection();// 此处的urlConnection对象实际上是根据URL的  
              // 请求协议(此处是http)生成的URLConnection类  
              // 的子类HttpURLConnection,故此处最好将其转化  
              // 为HttpURLConnection类型的对象,以便用到  
              // HttpURLConnection更多的API.如下:  
      
    HttpURLConnection httpUrlConnection = (HttpURLConnection) rulConnection;  
     
    3、HttpURLConnection对象参数问题
    Java代码  
    // 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在  
    // http正文内,因此需要设为true, 默认情况下是false;  
    httpUrlConnection.setDoOutput(true);  
      
    // 设置是否从httpUrlConnection读入,默认情况下是true;  
    httpUrlConnection.setDoInput(true);  
      
    // Post 请求不能使用缓存  
    httpUrlConnection.setUseCaches(false);  
      
    // 设定传送的内容类型是可序列化的java对象  
    // (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)  
    httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");  
      
    // 设定请求的方法为"POST",默认是GET  
    httpUrlConnection.setRequestMethod("POST");  
      
    // 连接,从上述第2条中url.openConnection()至此的配置必须要在connect之前完成,  
            httpUrlConnection.connect();  
     
    4、HttpURLConnection连接问题
    Java代码  
    // 此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,  
    // 所以在开发中不调用上述的connect()也可以)。  
    OutputStream outStrm = httpUrlConnection.getOutputStream();  
     
    5、HttpURLConnection写数据与发送数据问题
    Java代码  
    // 现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。  
    ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm);  
      
    // 向对象输出流写出数据,这些数据将存到内存缓冲区中  
    objOutputStrm.writeObject(new String("我是测试数据"));  
      
    // 刷新对象输出流,将任何字节都写入潜在的流中(些处为ObjectOutputStream)  
    objOutputStm.flush();  
      
    // 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中,  
    // 在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器  
    objOutputStm.close();  
      
    // 调用HttpURLConnection连接对象的getInputStream()函数,  
    // 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。  
    InputStream inStrm = httpConn.getInputStream(); // <===注意,实际发送请求的代码段就在这里  
      
    // 上边的httpConn.getInputStream()方法已调用,本次HTTP请求已结束,下边向对象输出流的输出已无意义,  
    // 既使对象输出流没有调用close()方法,下边的操作也不会向对象输出流写入任何数据.  
    // 因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、  
    // 重新发送数据(至于是否不用重新这些操作需要再研究)  
    objOutputStm.writeObject(new String(""));  
    httpConn.getInputStream();  
     
    6、post参数的方法
    Java代码  
    OutputStream os = httpConn.getOutputStream();  
                String param = new String();  
                param = "CorpID=" + CorpID +  
                        "&LoginName=" + LoginName+  
                        "&send_no=" + phoneNumber +  
                        "&msg=" + java.net.URLEncoder.encode(msg,"GBK"); ;  
                os.write(param.getBytes());  
     
    7、超时设置,防止 网络异常的情况下,可能会导致程序僵死而不继续往下执行
    Java代码  
    System.setProperty("sun.net.client.defaultConnectTimeout", "30000");  
    System.setProperty("sun.net.client.defaultReadTimeout", "30000");  
      
    其中: sun.net.client.defaultConnectTimeout:连接主机的超时时间(单位:毫秒)  
    sun.net.client.defaultReadTimeout:从主机读取数据的超时时间(单位:毫秒)  
      
    JDK 1.5以前的版本,只能通过设置这两个系统属性来控制网络超时。在1.5中,还可以使用HttpURLConnection的父类URLConnection的以下两个方法:  
    setConnectTimeout:设置连接主机超时(单位:毫秒)  
    setReadTimeout:设置从主机读取数据超时(单位:毫秒)  
      
    例如:  
    HttpURLConnection urlCon = (HttpURLConnection)url.openConnection();  
    urlCon.setConnectTimeout(30000);  
    urlCon.setReadTimeout(30000);  
     
     
     
    总结:
     
    a: HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
        无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
           b:在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,
        对connection对象的一切配置(那一堆set函数)
        都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。
        这些顺序实际上是由http请求的格式决定的。
        如果inputStream读操作在outputStream的写操作之前,会抛出例外:
        java.net.ProtocolException: Cannot write output after reading input.......
           
           c:http请求实际上由两部分组成,
        一个是http头,所有关于此次http请求的配置都在http头里面定义,
               一个是正文content。
        connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,
        就必须把所有的配置准备好。
           d: 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,
        实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,
        而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。
        至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求
        正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http
        请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数
        之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)
        都是没有意义的了,执行这些操作会导致异常的发生。

    展开全文
  • 各位大侠好,最近在做的一个工具时HttpURLConnection访问一...用 sleep 和 Timer 都不行,就好像直接跳过这两句了,其实要实现的功能就是:java 连接一个视频网站,然后模拟在看视频。请问各位大侠这个应该要怎么实现?
  • URLConnection

    万次阅读 多人点赞 2018-10-05 11:01:51
    URLConnection是一个抽象类,表示指向URL指定资源的活动连接URLConnection有两个不同但相关的用途: URLConnection可以检查服务器发送的首部,并相应地做出响应。它可以设置客户端请求中使用的首部字段。最后...

    简介

    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()
    

    如果使用了代理,返回true,否则返回false;

    以上只是学习所做的笔记!!!
    书籍:Java网络编程

    展开全文
  • URLConnection-URL连接

    2021-11-05 21:36:02
    本文介绍了 URLConnection java类; 1. 按理URL 有获取网络资源的接口(getContent(), getFile()),为啥还要封装 URLConnection ? URL 获取资源方法如下: 很显然, URL 只提供了客户端与服务器简单交互的...

    【README】

    • 本文介绍了 URLConnection java类,通过 URLConnection 如何获取网络资源;
    • 本文还梳理了涉及网络编程的java类的进化过程;从 URL -> URLConnection -> HttpURLConnection 或 HttpClient
    • URL与URI的介绍, refer2   java URL和URI_PacosonSWJTU的博客-CSDN博客

    1. 按理URL 有获取网络资源的接口(如getContent(), getFile()),为啥还要封装 URLConnection ? URL 获取资源方法如下:

    2. 很显然, URL 只提供了客户端与服务器简单交互的功能,没有提供复杂的交互功能,比如请求头,缓存,字符编码,鉴权,等等,并根据请求头做出不同响应啊等等;所以引入 URLConnection来封装客户端与服务器间的复杂功能;

    • 2.1 URL 与 URLConnection 两者间还有一个重要区别:
      • 2.1.1 URL 只能读取网络资源内容(单向),而 URLConnection 提供了不仅从服务器读取数据,还有向服务器写入数据的功能,是双向交互;

    3. 小结: URL 和 URLConnection的不同点

    • URLConnection 提供了对http的首部访问接口;
    • URLConnection 可以配置发送给服务器的请求参数;
    • URLConnection除了可以读取数据之外,还可以向服务器写入数据; (数据流是双向)

    4.  那为啥还要在 URLConnection的基础上 引入 HttpURLConnection ?

    abstract public class HttpURLConnection extends URLConnection {

     HttpURLConnection  继承了 URLConnection, 前者对后者的功能进行了扩展,以提供基于http协议的api,最显著的差别是,提供了获取错误输入流,响应码等方法,这是 URLConnection做不到的(根据下图的方法列表,HttpURLConnection也只是一点点扩展);

    5.  我们再深入一下,既然有了 HttpURLConnection,那为啥 apache 还提供了 HttpClient-http客户端工具包进行网络编程?

    在通常状况下,若是只是须要向Web站点的某个简单页面提交请求并获取服务器响应,HttpURLConnection彻底能够胜任。
    但访问一些页面需要复制操作如鉴权,这就涉及Session、Cookie的处理了,若是打算使用HttpURLConnection来处理这些细节,固然也是可能实现的,只是处理起来难度就大了
    因此 为了简化复杂的http网络编程,apache提供了HttpClient工具包;

    补充: 第5点并不是说不用 HttpURLConnection,全部用 HttpClient ;

    要知道, 性能上 HttpURLConnection高于 HttpClient,简单网络请求用 HttpURLConnection更快,复杂请求如 保存会话session,cookie,使用缓存等 使用 HttpClient;可以理解为 HttpURLConnection 是 轻量级网络请求, HttpClient 封装了其他额外的功能,比较重量级

    但是我们写底层框架的时候,一般用的都是 HttpURLConnection,因为它是jdk自带的,HttpClient 需要额外引入apache依赖,不便于后期框架代码维护);


    6. 下面给出 使用 URL, URLConnection, HttpURLConnection, HttpClient 读取网络资源的代码示例

    • 6.1 根据 URL 获取资源
    // 根据 URL 获取资源
        @Test
        public void f0 () throws Exception {
            URL url = new URL("http://www.baidu.com");
            try (InputStream inputStream = url.openStream()) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String result = "";
                while((result = bufferedReader.readLine()) != null) {
                    System.out.println(result);
                }
            }
        }
    • 6.2  根据 URLConnection 获取资源
    // 根据 URLConnection 获取资源
        @Test
        public void f1() throws Exception {
            URL u = new URL("http://www.baidu.com");
            // 打开连接获取 URLConnection对象
            URLConnection uc = u.openConnection();
            uc.setAllowUserInteraction(true);
    
            // 读取资源信息
            System.out.println("过期时间 " + uc.getExpiration());
            System.out.println("报文长度 " + uc.getContentLength());
            System.out.println("最后修改时间" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(uc.getLastModified())));
    
            // try资源块-自动关闭输入流
            try (InputStream inputStream = uc.getInputStream()) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                // 打印从服务器读取的报文
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.println(line);
                }
            }
        }
    • 6.3 根据 HttpURLConnection 获取资源
    // 根据 HttpURLConnection 获取资源
        @Test
        public void f1_1() throws Exception {
            URL u = new URL("http://www.baidu.com");
            // 获取 HttpURLConnection 连接
            HttpURLConnection httpUc = (HttpURLConnection) u.openConnection();
    
            // try资源块-自动关闭输入流
            try (InputStream inputStream = httpUc.getInputStream()) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                // 打印从服务器读取的报文
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.println(line);
                }
            }
        }
    • 6.4 根据 apache HttpClient 获取资源
    // 根据 apache HttpClient 获取资源
        @Test
        public void f1_2()  {
            //1.获得一个httpclient对象
            CloseableHttpClient httpclient = HttpClients.createDefault();
            //2.生成一个get请求
            HttpGet httpget = new HttpGet("http://www.baidu.com");
            //3.执行get请求并返回结果
            try (CloseableHttpResponse response = httpclient.execute(httpget)) {
                // 判断响应码
                if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                    // 读取报文
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));
                    String line = "";
                    while((line = bufferedReader.readLine()) != null) {
                        System.out.println(line);
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException("请求错误");
            }
        }

     【1】URLConnection 简要介绍

    1)URLConnection 是java的协议处理器机制的一部分,这个机制还包括 URLStatementHandler 类;

    【1.1】打开 URLConnection

    1)打开 URLConnection 与服务器交互步骤

    1. 构造 URL 对象;
    2. 调用 URL.openConnection() 获取 URLConnection 对象;
    3. 配置这个 URLConnection对象;
    4. 读取首部字段;(或有)
    5. 获取输入流并读取数据  调用 URLConnection.getInputStream() ; (或有)
    6. 获取输出流并写入数据; (或有)
    7. 关闭连接; 
    // 打开 URLConnection 与服务器交互
        @Test
        public void f1() throws Exception {
            URL u = new URL("http://www.baidu.com");
            // 打开连接获取 URLConnection对象
            URLConnection uc = u.openConnection();
            uc.setAllowUserInteraction(true);
            try (InputStream inputStream = uc.getInputStream()) { // try资源块-自动关闭输入流
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                // 打印从服务器读取的报文
                String line = "";
                while((line = bufferedReader.readLine()) != null) {
                    System.out.println(line);
                }
            }
        }

    【1.2】URLConnection 读取首部(请求头或响应头)

    1)http首部包括 所请求网络资源的内容类型,长度,内容编码字符集,日期时间,内容过期时间,内容最后修改时间;

    【1.2.0】常用首部包括:

    1. Content-type; 内容类型; MIME 内容类型; URLConnection.getContentType()
    2. Content-length;内容字节长度; URLConnection.getContentLength()
    3. Content-encoding,内容编码(非字符编码,字符编码格式在 content-type中的mime类型指定); URLConnection.getContentEncoding()
    4. Date, 内容产生时间; URLConnection.getDate()
    5. Last-modified, 最后修改时间, 以便于缓存; URLConnection.getLastModified()
    6. Expires, 到期时间, 以便于缓存;  URLConnection.getExpiration()

    【1.2.1】 getContentType 返回响应主体的 MIME内容类型 (多用途互联网邮件扩展类型)

    1)常用的 mime类型包括

    • text/html
    • text/plain
    • image/gif
    • application/xml
    • image/jpeg
    • application/json

    2)如果内容类型是某种类型文本,那这个首部可能还包含一个字符集部分来标识文档的字符编码格式,如:

    Content-type: text/html; charset=UTF-8 或  Content-type: application/json; charset=UTF-8

    【1.2.2】getContentLength 获取响应报文体字节个数

    • 1)getContentLength 返回是 int 类型,最多标识 2gb(2^31=2g=20亿字节);
    • 2)随着网络发展,实际上很有可能资源大小超过 2gb; 在这种情况下 getContentLength 返回-1;

    java7 新增了 getContentLengthLong 方法 返回类型是long, 2^63 个字节,理论上可以接收 8000PB=800万TB 个字节,足够使用了;

    【1.2.3】getContentEncoding() 获取内容编码格式

    web上常用的内容编码格式 可能是 x-gzip  或  GZipInputStream 直接解码;

    【1.2.4】getDate()  指出文档发送给客户端的时间;

    【1.2.5】getExpiration()  文档在服务器的过期时间

    • 1)提示客户端应该何时从缓存中删除文档,并从服务器重新下载;
    • 2)如果http首部没有 expiration字段,getExpiration() 返回0, 表示文档不会过期,将永远保留在缓存中;

    【1.2.6】getLastModified 返回文档的最后修改时间

    例子1, 读取http常用响应头

    // 读取http常用响应头
        @Test
        public void f0() throws Exception {
            // 格式化器
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
            // 读取 URLConnection 的常用响应头
            URL url = new URL("http://www.baidu.com");
            URLConnection urlConnection = url.openConnection();
            // 读取资源内容类型, mime 类型
            System.out.println("内容类型 = " + urlConnection.getContentType());
            // 读取资源内容长度
            System.out.println("内容长度 = " + urlConnection.getContentLength());
            // 读取资源内容编码(如gzip,不是字符编码,字符编码在 content-type中的mime类型指定)
            System.out.println("内容编码 = " + urlConnection.getContentEncoding());
            // 读取指出文档发送给客户端的时间
            System.out.println("指出文档发送给客户端的时间 = " + simpleDateFormat.format(urlConnection.getDate()));
            // 读取文档在服务器的过期时间
            System.out.println("文档在服务器的过期时间 = " + simpleDateFormat.format(urlConnection.getExpiration()));
            // 读取 文档的最后修改时间
            System.out.println("文档的最后修改时间  = " + simpleDateFormat.format(urlConnection.getLastModified ()));
        }

    结果:

    内容类型 = text/html
    内容长度 = 2381
    内容编码 = null
    指出文档发送给客户端的时间 = 2021-11-06 12:02:00
    文档在服务器的过期时间 = 1970-01-01 08:00:00
    文档的最后修改时间  = 1970-01-01 08:00:00

    例子2,读取二进制资源文件,如图片(百度上随便搜索一张),mime类型为 image/jpeg ;

    @Test
        public void f1() throws Exception {
            URL url = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F18%2F08%2F24%2F05dbcc82c8d3bd356e57436be0922357.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638764377&t=703444b029255bfa2ddba73484dd7c7c");
            // 打开连接,判断是否为图片格式
            URLConnection urlConnection = url.openConnection();
            String contentType = urlConnection.getContentType();
    //        long contentLength = urlConnection.getContentLengthLong();
            int contentLength = urlConnection.getContentLength();
            System.out.println("文件内容类型=" + contentType + ", 内容长度=" + contentLength);
            if (!contentType.startsWith("image") || contentLength < 1) {
                throw new IOException("不是一个图片文件");
            }
            // 读取资源
            try (BufferedInputStream bufferedInputStream = new BufferedInputStream(url.openStream())) {
                byte[] data = new byte[contentLength];
                int offset = 0;
                int byteread = 0;
                while(offset < contentLength) {
                    if ((byteread = bufferedInputStream.read(data, offset, data.length - offset)) == -1) {
                        break;
                    }
                    offset += byteread;
                }
                if (offset != contentLength) {
                    throw new IOException(MessageFormat.format("读取失败, 读了{0}个字节,期望读取{1}个字节", offset, contentLength));
                }
                // 写入文件,获取文件名
                String filename = url.getFile();
                System.out.println("资源文件名 = " + filename);
                filename = "temp01." + contentType.split("[\\W+]")[1];// 非词字符正则分割
               try (FileOutputStream fos = new FileOutputStream("D:/temp/" + filename)) {
                   fos.write(data);
                   fos.flush();
               }
            }
        }

    结果:

    文件内容类型=image/jpeg, 内容长度=46417


    【1.3】获取任意首部

    // 获取任意首部
        @Test
        public void f1() throws Exception {
            URL url = new URL(
                    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.588ku.com%2Felement_origin_min_pic%2F18%2F08%2F24%2F05dbcc82c8d3bd356e57436be0922357.jpg&refer=http%3A%2F%2Fbpic.588ku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638764377&t=703444b029255bfa2ddba73484dd7c7c");
            URLConnection urlConnection = url.openConnection();
            // 获取所有首部(响应头)的键值对
            Map<String, List<String>> headerFileds = urlConnection.getHeaderFields();
            Set<Map.Entry<String, List<String>>> entrySet = headerFileds.entrySet();
            entrySet.forEach(entry -> {
                String key = entry.getKey();
                System.out.println("key = " + key + ", 值列表=" + entry.getValue());
            }); 
            // 获取单个首部
            System.out.println("获取单个首部");
            System.out.println("Content-Type = " + urlConnection.getHeaderField("Content-Type"));
        }

    结果:

    key = null, 值列表=[HTTP/1.1 200 OK]
    key = Server, 值列表=[JSP3/2.0.14]
    key = Access-Control-Allow-Origin, 值列表=[*]
    key = Ohc-Upstream-Trace, 值列表=[118.112.225.100]
    key = Connection, 值列表=[keep-alive]
    key = Last-Modified, 值列表=[Thu, 01 Jan 1970 00:00:00 GMT]
    key = Ohc-File-Size, 值列表=[46417]
    key = Date, 值列表=[Sat, 06 Nov 2021 04:42:29 GMT]
    key = Accept-Ranges, 值列表=[bytes]
    key = Ohc-Cache-HIT, 值列表=[cd6ct100 [4], bdix100 [4]]
    key = Ohc-Response-Time, 值列表=[1 0 0 0 0 0]
    key = ETag, 值列表=[927f0861741bd2135df3cbac979cdded]
    key = Timing-Allow-Origin, 值列表=[*]
    key = Expires, 值列表=[Sat, 04 Dec 2021 06:42:40 GMT]
    key = Content-Length, 值列表=[46417]
    key = Age, 值列表=[1287]
    key = Content-Type, 值列表=[image/jpeg]
    获取单个首部
    Content-Type = image/jpeg


    【2】 缓存

    【2.1】缓存涉及的 http报文头

    1)Expires 报文头指示这个资源可以缓存,期限是指定的时间为止;

    2)Cache-control 首部提供了更加细粒度的缓存策略;

    Cache-control 会覆盖 Expires ,即优先级 前者高于后者;服务器可以在一个首部中发送多个 Cache-control 首部,只要它们没有冲突; 

    3)Last-modified 指示资源最后一次修改日期。只有当本地缓存的副本早于这个日期,才会到服务器获取资源,否则客户端一直使用本地缓存;

    4)Etag首部: 资源改变时的唯一标识; 当客户端资源副本的Etag 与 服务器不同时,才会到服务器获取资源,否则客户端一直使用本地缓存;

    5)缓存策略(干货):

    1. 如果本地缓存中有这个资源的一个表示, 而且还没有到它的过期时间 Expires,那么可以直接使用这个资源,而无需请求服务器;
    2. 如果本地缓存中有这个资源的一个表示,但到了过期时间,在完成 get请求前,可以检查服务器首部的head首部 Etag,查看资源是否已经改变;

    6)java自带的web缓存类

    默认情况下,java并没有缓存。需要安装URL类使用的系统级缓存,需要有:

    • ResponseCache的子类;
    • CacheRequest的子类;
    • CacheResponse的子类;

    【3】配置 URLConnection连接

    【3.1】配置属性及其方法

    1)URLConnection定义了7个保护字段,定义了客户端如何向服务器发送请求;

    • 1.1)protected URL url, 指定这个 URLConnection 连接 URL;初始化一次,不能修改;
    • 1.2)protected boolean connected,是否连接;连接打开,该值为true,连接关闭,该值为false;connect(), getInputStream(), getOutputStream() 都会打开连接; disconnect() 关闭连接; 
    • 1.3)protected boolean allowUserInteraction, 指示了是否允许用户交互;只能在打开连接前设置,连接后设置抛出异常;
    • 1.4)protected boolean doInput,是否可以从服务器服务器读取资源;补充 URConnection 可以用于读取服务器,写入服务器,或读写服务器;但响应字段要设置为true;
    • 1.5)protected boolean doOutput,是否可以向服务器写入数据; 当为一个 http URL的doOutput设置为 true时,请求方法从 GET 修改为 POST
    • 1.6)protected boolean ifModifiedSince,设置为true,则客户端请求报文头包括一个首部 If-Modified-Since,值日期时间格式;如果服务器文档在这个时间之后修改,则发送该文档,否则不发送(而发送响应码 304 Not Modified),客户端使用本地缓存;  URLConnection的 ifModifiedSince 字段指定了 放置在 If-Modified-Since 首部字段中的日期,调用 setIfModifiedSince(long ifModifiedSince毫秒数) 来设置;
    • 1.7)protected boolean useCaches, 客户端是否使用本地缓存; URCConnection.setUseCahces(false) 用于禁用本地缓存; 

    2)URLConnection 连接属性设置例子

     // URCConnection 连接属性设置例子
        @Test
        public void f3() throws Exception {
            URL u = new URL("http://www.baidu.com");
            // 打开连接获取 URLConnection对象
            URLConnection uc = u.openConnection();
            uc.setAllowUserInteraction(true); // 允许交互
            uc.setDoInput(true);  // 可以从服务器读取数据
            uc.setDoOutput(true); // 可以向服务器写入数据
            uc.setIfModifiedSince(new Date().getTime()); // 设置资源最后修改时间
            uc.setUseCaches(false); // 禁用缓存
    
            // try资源块-自动关闭输入流
            try (InputStream inputStream = uc.getInputStream()) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                // 打印从服务器读取的报文
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.println(line);
                }
            }
        }

    【3.2】超时

    • setConnectionTimeout(int),设置连接获取超时时间;
    • setReadTimeout(int) ,设置读取服务器资源超时时间; 

    【4】配置客户端请求http首部

    【4.1】增加首部字段

    1) URLConnection.setRequestProperty(String name, String value) 为http首部增加字段;

    其允许一个name,有多个value,多个value通过逗号隔开; 该方法只能在 打开连接前使用;

    【4.2】向服务器写入数据

    // 向服务器写入数据
        @Test
        public void f4() throws Exception {
            URL u = new URL("http://www.baidu.com");
            // 打开连接,把请求方法从get变为post
            URLConnection uc = u.openConnection();
            uc.setDoOutput(true); // get 变为 post
            uc.setRequestProperty("cookie", "username=zhangsan; password=123456; session=B2C7E8A1F2F5E8"); // 设置cookie请求头  
    
            // 写入数据到server
            try(OutputStream outputStream = uc.getOutputStream()) {
                outputStream.write("四川省成都市高新区".getBytes(StandardCharsets.UTF_8));
            }
            System.out.println("写入数据成功,bingo");
        }

    【5】HttpURLConnection

    HttpURLConnection 是抽象类,构造函数是保护类型,所以不能直接创建;

    URL.openConnection() 返回的就是一个 HttpURLConnection的一个实例; 如下:

    URL u = new URL("http://www.baidu.com");
    // 获取 HttpURLConnection 连接
    HttpURLConnection httpUc = (HttpURLConnection) u.openConnection();

    【5.1】 请求方法

    1)改变请求方法

    HttpURLConnection.setRequestMethod() 用于修改请求方法;

    2)请求方法包括:

    • GET,请求资源,但没有请求体;
    • POST,请求资源, 有请求体;
    • HEAD,告诉服务器只返回http首部,不用实际发送文件 ;常见用途是检查文件的最后修改时间;
    • PUT,html编辑器或向上传文件到服务器使用put方法;
    • DELETE,删除web服务器上的文件;
    • OPTIONS,询问某个url 支持哪些选项;
    • TRACE ,trace会发送http报文头,服务器接收这个报文头;可以查看 服务器和客户端之间的代理服务器做了哪些修改;

    3)restful api中 方法类型与业务操作对应关系

    序号方法类型业务操作
    1get查询数据
    2post新增数据
    3put修改或更新数据
    4delete删除数据

    【5.2】断开与服务器的连接

    调用 HttpURLConnection.disconnect() 方法可以关闭连接,同时关闭流;但关闭流不会关闭连接;

    【5.3】处理服务器响应

    1)响应报文示例

     

    注意: 响应报文头 与 响应实体间 有一个空行(作为分隔符),图片中我忘记标识出来了,特此说明

     2)获取响应码和响应报文

    // 获取响应码和响应报文
        @Test
        public void f6() throws Exception {
            URL u = new URL("http://www.baidu.com");
            // 打开连接,把请求方法从get变为post
            HttpURLConnection httpURLConnection = (HttpURLConnection) u.openConnection();
            System.out.println("响应码  = " + httpURLConnection.getResponseCode());
            System.out.println("响应消息  = " + httpURLConnection.getResponseMessage());
    
            // 获取所有响应头
            for (int i = 1; ; i++) {
                String header = httpURLConnection.getHeaderField(i);
                String key = httpURLConnection.getHeaderFieldKey(i);
                if (header == null || key == null) break;
                System.out.println("key=" + key + ", value=" + header);
            }
        }

    打印结果:

    响应码  = 200
    响应消息  = OK
    key=Content-Length, value=2381
    key=Content-Type, value=text/html
    key=Server, value=bfe
    key=Date, value=Sat, 06 Nov 2021 08:51:40 GMT

    3)补充:HttpURLConnection 封装了很多常量响应码

    展开全文
  • URL可以被认为是指向互联网资源的“指针”,通过URL可以获得互联网资源相关信息,包括获得URL的InputStream对象获取资源的信息,以及一个到URL所引用远程对象的连接URLConnectionURLConnection对象可以向所代表...
  • // 因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、   // 重新发送数据(至于是否不用重新这些操作需要再研究)   objOutputStm.writeObject( new  String( ...
  • 1.Socket 的连接是有状态的,一旦两边连接上了,将一直保持连接,除非人为断开。一般用于游戏,需要持续的网络畅通...HttpURLConnection继承自URLConnection,差别在与HttpURLConnection仅仅针对Http连接。 HttpURLConn
  • 我使用 AsyncTask来连接一个 URLPath: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.left_list); Button btn = ...
  • URLConnection类详解

    2019-07-24 10:42:00
    URLConnection是一个抽象类,表示指向URL指定资源的活动连接URLConnection类本身依赖于Socket类实现网络连接。一般认为,URLConnection类提供了比Socket类更易于使用、更高级的网络连接抽象。但实际上,大多数.....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,998
精华内容 3,999
关键字:

urlconnection关闭连接