zoukankan      html  css  js  c++  java
  • HttpURLConnection模拟浏览器http请求【转】

    本文是参考网络文章测试整理,报歉忘记参考地址了,要是作者有意见就请联系我.文中只是对程序的运行做了测试,但理论没有去考证正确性,等后面研究下再完善.这只是做参考 

      1 import java.io.BufferedReader;
      2 import java.io.DataOutputStream;
      3 import java.io.InputStreamReader;
      4 import java.net.HttpURLConnection;
      5 import java.net.URL;
      6 import java.net.URLEncoder;
      7 
      8 /**
      9  * HttpURLConnection 模拟浏览器http请求处理测试
     10  * 
     11  * 整体操作流程(注意顺序)
     12  *   1.根据url地址创建URL对象
     13  *   2.url.openConnection() 得到HttpURLConnection
     14  *   3.设置HttpURLConnection的配置(会根据配置生成http请求头信息)
     15  *   4.httpConn.connect()建立与服务器的TCP连接
     16  *   5.通过httpConn得到输出流,并写入参数
     17  *   6.通过httpConn得到输入流,并读取服务器返回信息(这时才真正产生http请求发送给服务器,但可以根据配置来改变;一般返回可能是html字符串)
     18  * 
     19  * httpRequestPost/httpRequestGet两种方式测试通过,返回的是html字符串(后台是jsp)
     20  *
     21  */
     22 public class HttpURLConnectionTest {
     23 
     24     public static void main(String[] strs) throws Exception{
     25         HttpURLConnectionTest t = new HttpURLConnectionTest();
     26         String url = "http://localhost:8080/URLTest/filesystem/fileBrowse.do";
     27         t.httpUrlConnection(url);
     28     }
     29     
     30     private void httpUrlConnection(String urlStr) throws Exception{
     31         httpRequestGet(urlStr);
     32         httpRequestPost(urlStr);
     33     }
     34     
     35     /**
     36      * http post请求
     37      * @param urlStr URL地址
     38      * @throws Exception
     39      */
     40     private void httpRequestPost(String urlStr) throws Exception{
     41         URL url = new URL(urlStr);
     42         
     43         HttpURLConnection httpConn = (HttpURLConnection)url.openConnection();
     44         
     45         //设置是否向connection输出,因为是post请求,参数要放在 http正文内,因此需要设为true
     46         httpConn.setDoOutput(true);
     47         
     48         //是否向connection输入,默认为true
     49         httpConn.setDoInput(true);
     50         
     51         //POST请求方式
     52         httpConn.setRequestMethod("POST");
     53         
     54         //post请求不能使用缓存
     55         httpConn.setUseCaches(false);
     56         
     57         //是否自动执行重定向,默认为true
     58         httpConn.setInstanceFollowRedirects(true);
     59         
     60         //配置本次连接的Content-type,配置为application/x-www-form-urlencoded的意思是正文是urlencoded编码过的form参数
     61         //下面我们可以看到我们对正文内容使用URLEncoder.encode 进行编码
     62         httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
     63         
     64         //连接,从openConnection()至此的配置必须要在connect之前完成, 注意的是connection.getOutputStream会隐含的进行connect。
     65         httpConn.connect();
     66         
     67         DataOutputStream dos = new DataOutputStream(httpConn.getOutputStream());
     68         
     69         //发送正文,正文内容其实跟get的URL中'?'后的参数字符串一致 word=wait&tn=news&from=news
     70         String content = "filePath=" + URLEncoder.encode("设计资料/设计", "utf-8");
     71         
     72         //DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写道流里面
     73         dos.writeBytes(content); 
     74         
     75         //刷新流
     76         dos.flush();
     77         
     78         //关闭流
     79         dos.close();
     80         
     81         // 取得输入流,并使用Reader读取
     82         BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
     83         
     84         System.out.println("=========post request接收数据内容开始============");
     85         String lines;
     86         while ((lines = reader.readLine()) != null) {
     87             System.out.println(lines);
     88         }
     89         reader.close();
     90         System.out.println("=========post request接收数据内容结束============");
     91         httpConn.disconnect();
     92     }
     93 
     94     /**
     95      * http get 请求
     96      * @param urlStr 请求URL地址
     97      * @throws Exception
     98      */
     99     private void httpRequestGet(String urlStr) throws Exception{
    100         //URL拼接,如:"http://www.baidu.com?name=HI,中国",这里对特殊字符进行了编码,不然会产生乱码
    101         URL url = new URL(urlStr + "?filePath=" + URLEncoder.encode("设计资料/设计", "utf-8"));
    102         
    103         //openConnection函数会根据URL的协议返回不同的URLConnection子类的对象
    104         //这里URL是一个http,因此实际返回的是HttpURLConnection 
    105         HttpURLConnection httpConn = (HttpURLConnection)url.openConnection();
    106         
    107         //进行连接,实际上request要在下一句的connection.getInputStream()函数中才会真正发到 服务器****待验证
    108         httpConn.connect();
    109         
    110          // 取得输入流,并使用Reader读取
    111         BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
    112         
    113         System.out.println("=========get request接收数据内容开始============");
    114         String lines;
    115         while ((lines = reader.readLine()) != null) {
    116             System.out.println(lines);
    117         }
    118         reader.close();
    119         System.out.println("=========get request接收数据内容结束============");
    120         httpConn.disconnect();
    121     }
    122 
    123     
    124     /**
    125      * http post 请求(未测试)
    126      * 
    127      * @param urlStr
    128      * @throws Exception
    129      */
    130     public static void httpRequestPostBig(String urlStr) throws Exception {
    131             URL postUrl = new URL(urlStr);
    132             HttpURLConnection connection = (HttpURLConnection) postUrl
    133                     .openConnection();
    134             connection.setDoOutput(true);
    135             connection.setDoInput(true);
    136             connection.setRequestMethod("POST");
    137             connection.setUseCaches(false);
    138             connection.setInstanceFollowRedirects(true);
    139             connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
    140              //与httpRequestPost()的不同,设置了块大小为5字节
    141             connection.setChunkedStreamingMode(5);
    142             connection.connect();
    143             /*
    144              * 注意,下面的getOutputStream函数工作方式于在httpRequestPost()里面的不同
    145              * 在httpRequestPost()里面该函数仍在准备http request,没有向服务器发送任何数据
    146              * 而在这里由于设置了ChunkedStreamingMode,getOutputStream函数会根据connect之前的配置
    147              * 生成http request头,先发送到服务器。
    148              */
    149             DataOutputStream out = new DataOutputStream(connection
    150                     .getOutputStream());
    151             String content = "name=" + URLEncoder.encode("发送到服务器                                                                             " +
    152                     "                                          " +
    153                     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "utf-8");
    154             out.writeBytes(content); 
    155 
    156             out.flush();
    157             out.close(); //到此时服务器已经收到了完整的http request了,而在httpRequestPost()函数里,要等到下一句getInputStream()服务器才能收到http请求。
    158             BufferedReader reader = new BufferedReader(new InputStreamReader(
    159                     connection.getInputStream()));
    160             
    161             out.flush();
    162             out.close();
    163             String line;
    164             System.out.println("==========post request开始==========");
    165             while ((line = reader.readLine()) != null) {
    166                 System.out.println(line);
    167             }
    168             System.out.println("==========post request结束==========");
    169             reader.close();
    170             connection.disconnect();
    171         }
    172 }

    HttpURLConnection.connect函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。无论是post还是get,http请求实际上直到HttpURLConnection.getInputStream()这个函数里 

    面才正式发送出去。 
      在httpRequestPost() 中,顺序很重要,对connection对象的一切配置(那一堆set函数)都必须要在connect()函数执行之前完成。而对 outputStream的写操作,又必须要在inputStream的 

    读操作之前。这些顺序实际上是由http请求的格式决定的。 
      http 请求实际上由两部分组成,一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文content,在connect()函数里面,会根据HttpURLConnection对象的配置值生 

    成http头,因此在调用connect函数之前,就必须把所有的配置准备好。 
      紧接着http头的是http请求的正文,正文的内容通过outputStream写入,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是在流关闭 

    后,根据输入的内容生成http正文。 
      至此,http请求的东西已经准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回 

    信息。由于http请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数之后对connection对象进行设置(对http头的信息进行修改)或者写入 outputStream 

    (对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生 
      post请求的OutputStream实际上不是网络流,而是写入内存,在getInputStream中才真正把写道流里面的内容作为正文与根据之前的配置生成的http request头合并成真正的http request, 

    并在此时才真正向服务器发送。 
      HttpURLConnection.setChunkedStreamingMode 函数可以改变这个模式,设置了ChunkedStreamingMode后,不再等待OutputStream关闭后生成完整的http request一次过发送,而是先发送 

    http request头,正文内容则是网路流的方式实时传送到服务器。实际上是不告诉服务器http正文的长度,这种模式适用于向服务器传送较大的或者是不容易获取长度的数据,如文件。

     

  • 相关阅读:
    POJ 1873 计算几何
    POJ 1584 计算几何
    POJ 1410 计算几何
    BZOJ 1208 set
    BZOJ 1503 splay
    BZOJ 5277 IQ题orz
    Codeforces Round #549 (Div. 2)A. The Doors
    (原创)同余定理
    April Fools Day Contest 2019 A. Thanos Sort
    PTA数据结构之 List Leaves
  • 原文地址:https://www.cnblogs.com/macula/p/2613779.html
Copyright © 2011-2022 走看看