• 【Java基础】- HttpURLConnection详解


    【Java基础】- HttpURLConnection详解

    一、HttpURLConnection简述

    HttpURLConnection一个抽象类是标准的JAVA接口,该类位于java.net包中,它提供了基本的URL请求,响应等功能。

    HttpURLConnection是基于http协议的,支持GET、POST、PUT、DELETE等各种请求方式。如果使用HTTPS协议请求,可以使用它的子类HttpsURLConnection完成更安全的请求操作。

    二、HttpURLConnection使用步骤

    1. 创建一个URL对象:URL url=new URL(“接口地址”)

    2. 调用URL对象的openConnection()来获取HttpURLConnection对象实例;

      HttpURLConnection connection= (HttpURLConnection) url.openConnection();

    3. 设置HTTP请求使用的方法:GET、POST或其他请求;

      connection.setRequestMethod(“GET”);

    4. 设置连接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头;

      connection.setConnectTimeout(6*1000);

      connection.setReadTimeout(6 * 1000);

    5. 调用getInputStream()方法获得服务器返回的输入流,然后输入流进行读取了;

      InputStream in = connection.getInputStream();

    6. 最后调用disconnect()方法将HTTP连接关掉;

      connection.disconnect();

    三、HttpURLConnection使用的方法

    • 设置连接参数方法
      编号方法名说明
      1setAllowUserInteraction如果为 true,则在允许用户交互(例如弹出一个身份验证对话框)的上下文中对此 URL 进行检查。
      2setDoInputURL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 true。
      3setDoOutputURL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 false
      4setIfModifiedSince有些协议支持跳过对象获取,除非该对象在某个特定时间点之后又进行了修改
      5setUseCaches如果为 true,则只要有条件就允许协议使用缓存。
      6setDefaultAllowUserInteraction默认值为 “sticky”,它是所有 URLConnection 的其中一种静态状态。此标志适用于下一个及后续创建的所有 URLConnection。
      7setDefaultUseCaches将此 URLConnectionuseCaches 字段的值设置为指定的值。
    • 设置请求头或响应体
      编号方法说明
      1setRequestProperty(key,value)设置一般请求属性。如果已存在具有该关键字的属性,则用新值改写其值。注:HTTP 要求所有能够合法拥有多个具有相同键的实例的请求属性,使用以逗号分隔的列表语法,这样可实现将多个属性添加到一个属性中。
      2addRequestProperty(key,value)添加由键值对指定的一般请求属性。此方法不会改写与相同键关联的现有值
    • 发送URL请求
      编号方法说明
      1getOutputStream建立实际连接之后,就是发送请求,把请求参数传到服务器,这就需要使用outputStream把请求参数传给服务器
    • 获取响应
      编号方法说明
      1getContent检索此 URL 连接的内容;此方法首先通过调用 getContentType 方法确定对象的内容类型;如果这是该应用程序第一次遇到的特定内容类型,则会创建适用于该类型的内容处理程序:
      如果该应用程序已使用 setContentHandlerFactory 方法建立了内容处理程序工厂实例,则调用此实例的 createContentHandler 方法,内容类型为其中的一个参数;结果为该内容类型的内容处理程序。
      如果尚未建立任何内容处理程序工厂,或者如果工厂的createContentHandler方法返回null`,则应用程序会加载以下名称的类
      2getHeaderField返回第 n 个头字段的值。如果少于 n+1 个字段,则返回 null。此方法可与 getHeaderFieldKey 方法配合使用,以迭代消息中的所有头
      3getInputStream返回从此打开的连接读取的输入流。 在读取返回的输入流时,如果在数据可供读取之前达到读入超时时间,则会抛出 SocketTimeoutException。
      4getResponseCode获取服务器的响应代码
      5getResponseMessage获取服务器的响应消息
      6getResponseMethod获取发送请求的方法
    • 相应的信息头用以下方法获取
      编码方法说明
      1getContentEncoding返回 content-encoding 头字段的值
      2getContentLength返回 content-length 头字段的值。
      3getContentType返回 content-type 头字段的值。
      4getDate返回 date 头字段的值。
      5getExpiration返回 expires 头字段的值。

    四、HttpURLConnection使用演示

    • Get方式
      public void testDoGet(){
              String api="";
              HttpURLConnection connection = null;
              InputStream in=null;
              BufferedReader reader=null;
              try{
                  //构造一个URL对象
                  URL url = new URL(api);
                  //获取URLConnection对象
                  connection= (HttpURLConnection) url.openConnection();
                  //getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,所以在开发中不调用connect()也可以)
                  in = connection.getInputStream();
                  //通过InputStreamReader将字节流转换成字符串,在通过BufferedReader将字符流转换成自带缓冲流
                  reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
                  StringBuilder sb = new StringBuilder();
                  String line = null;
                  //按行读取
                  while ((line = reader.readLine()) != null) {
                      sb.append(line);
                  }
                  String response= sb.toString();
                  System.out.println(response);
              }catch (Exception exception){
                  exception.printStackTrace();
              }finally {
                  if (connection != null) {
                      connection.disconnect();
                  }
                  if (in != null) {
                      try {
                          in.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if (reader != null) {
                      try {
                          reader.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
    • POST方式
       public void testDoPost(){
              String apiUrl = "https://www.goyeer.com/api";
              String username  = "Goyeer";
              String password  = "123456";
              String tenantUrl = "";
              HttpURLConnection conn = null;
              OutputStream out = null;
              InputStream in = null;
              String idToken = null;
              try
              {
                 // 构造一个URL对象
                  URL url = new URL(apiUrl);
                  // 获取URLConnection对象
                  conn = (HttpURLConnection) url.openConnection();
                  // 限制socket等待建立连接的时间,超时将会抛出java.net.SocketTimeoutException
                  conn.setConnectTimeout(3000);
                  // 限制输入流等待数据到达的时间,超时将会抛出java.net.SocketTimeoutException
                  conn.setReadTimeout(3000);
                  // 设定请求的方法为"POST",默认是GET
                  conn.setRequestMethod("POST");
                  // 设置传送的内容类型是json格式
                  conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
                  // 接收的内容类型也是json格式
                  conn.setRequestProperty("Accept", "application/json;charset=utf-8");
                  // 设置是否从httpUrlConnection读入,默认情况下是true
                  conn.setDoInput(true);
                  // 由于URLConnection在默认的情况下不允许输出,所以在请求输出流之前必须调用setDoOutput(true)。为一个HTTP URL将doOutput设置为true时,请求方法将由GET变为POST
                  conn.setDoOutput(true);
                  // 是否使用缓存,Post方式不能使用缓存
                  conn.setUseCaches(false);
                  // 准备数据
                  JSONObject json = new JSONObject();
                  json.put("username", username);
                  json.put("password", DigestUtils.md5Hex(password));
                  json.put("tenantUrl", tenantUrl);
                  // 返回一个OutputStream,可以用来写入数据传送给服务器
                  out = conn.getOutputStream();
                  // 将数据写入到输出流中
                  out.write(json.toString().getBytes(StandardCharsets.UTF_8));
                  // 刷新管道
                  out.flush();
                  // 建立连接
                  conn.connect();
                  // 判断数字响应码是否是200
                  int responseCode = conn.getResponseCode();
                  String result="";
                  if (responseCode == 200) {
                      // 获取输入流
                      in = conn.getInputStream();
                      // 获取返回的内容
                      StringWriter sw = new StringWriter();
                      InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
                      char[] buffer = new char[4096];
                      for (int n = 0; -1 != (n = reader.read(buffer)); ) {
                          sw.write(buffer, 0, n);
                      }
                      result = sw.toString();
                      System.out.println(result);
                  }
              }catch (Exception exception){
                  exception.printStackTrace();
              }finally {
                  if (conn != null) {
                      conn.disconnect();
                  }
                  if (out != null) {
                      out.close();
                  }
                  if (in != null) {
                      in.close();
                  }
              }
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74

    五、HttpURLConnection使用总结

    • HttpURLConnection对象不能直接构造,需使用URL类中的openConnection()方法来创建实例

    • HttpURLConnection对象属性设置,需在connect()方法执行之前完成HttpURLConnection的connect()函数,其本质是建立一个与服务器的TCP连接,但并未实际发送HTTP请求 HTTP请求靠调用getInputStream()、getResponseCode()等方法触发,HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现
      不设置超时(timeout),当网络异常的情况下,可能会导致程序僵死而不继续往下执行

    • HTTP正文的内容是通过OutputStream流写入,向流中写入的数据不会立即发送到网络,而是存在于内存缓冲区中,待流关闭时,根据写入的内容生成HTTP正文。

    • 调用getInputStream()方法时,会返回一个输入流,用于从中读取服务器对于HTTP请求的返回信息

    • 当获取HTTP响应的时候,请求就会自动的发起

    • 如使用HttpURLConnection.getInputStream()方法的时系统会自动调用connect()方法

    • JDK8自带的HttpURLConnection 默认启用keepAlive,支持HTTP / 1.1和HTTP / 1.0持久连接,使用后的HttpURLConnection会放入缓存中供以后的同host:port的请求重用底层socket在keepAlive超时之前不会关闭。

    • 当在HttpURLConnection的header中加入Connection: close,则此连接不会启用keepAlive如果想启用keepAlive,程序请求完毕后必须调用HttpURLConnection.getInputStream().close()(此操作用于归还长连接给缓存,下次同host:port的请求重用底层socket连接),而不调用HttpURLConnection.disconnect()(表示关闭底层socket连接,不会启用keepAlive)。

  • 相关阅读:
    Java基础:集合类之ArrayList、HashMap简介
    一图看懂 6 种 API 架构模式
    智能合约引领:探索Web3的商业革新之路
    【Web漏洞探索】跨站脚本漏洞
    初阶C++__STL__string类(使用方法+模拟实现+测试+思路分析)
    相机标定基本原理
    综述--知识蒸馏
    什么是系统集成项目管理工程师,证书难考吗?
    Django REST项目实战:在线中文字符识别
    数据仓库(7)数仓规范设计
  • 原文地址:https://blog.csdn.net/songjianlong/article/details/131095601