HTTP通信模拟表单提交数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTP通信模拟表单提交数据相关的知识,希望对你有一定的参考价值。

  前面记录过一篇关于http通信,发送数据的文章:http://www.cnblogs.com/hyyq/p/7089040.html,今天要记录的是如何通过http模拟表单提交数据

一、通过GET请求方式提交:最简单的一种方式

  直接在链接后面跟上要提交的数据即可,比如: http://yychf.55555.io/get.do?username=yyc&password=yychf,通过http直接发送。然后在服务器端可以通过request.getParameter()方法来获得参数值。如要获得参数username的值可以通过request.getParameter("username");

二、通过POST请求方式提交:发送更多数据

  post请求方式参数比较隐蔽,数据的传输在请求的数据体中。一般来说,我们用POST提交表单会出现在前端html代码中,通过submit将数据提交到表单地址中,现在需要通过纯java代码实现表单的提交。其实原理也很简单,主要需要注意以下两点:

  1. 作为表单提交数据,需要设置它的请求头,主要是Content-Type的值, 这里的值是application/x-www-form-urlencoded
  2. 需要将参数转换成如key1=urlencode(value1)&key2=urlencode(value2)的形式,这里的urlencode是指将参数值用urlencode编码,其实就是是将表单字段和经过编码的字段值经过组合以数据体的方式做了参数传递。

  下面是具体实现代码:

  1 /**
  2      * 发起http请求
  3      * 发送参数(仿表单提交效果):
  4      * 基本思路:1.请求头“Content-Type”的值为“application/x-www-form-urlencoded”
  5      *           2.将参数拼接成key=value形式的字符串post提交
  6      *            注意:key=value中key,value即参数名、值不能有中文字符,
  7      *            所以发送的数据就是key1=urlencode(value1)&key2=urlencode(value2)&...形式的字符串
  8      * @param urlString
  9      * @param formProperties
 10      * @return
 11      * @throws Exception
 12      */
 13     public static byte[] httpRequestPostForm(String urlString,Properties formProperties) throws Exception{
 14 
 15         //设置http请求头信息
 16         Properties requestProperties = new Properties();
 17         requestProperties.setProperty("Content-Type", "application/x-www-form-urlencoded");
 18 
 19 
 20         //将需要发送的参数拼接成key1=urlencode(value1)&key2=urlencode(value2)&...形式的字符串
 21         StringBuilder sb = new StringBuilder();
 22         if ((formProperties != null) && (formProperties.size() > 0)) {
 23             for (Map.Entry<Object, Object> entry : formProperties.entrySet()) {
 24                 String key = String.valueOf(entry.getKey());
 25                 String value = String.valueOf(entry.getValue());
 26                 sb.append(key);
 27                 sb.append("=");
 28                 sb.append(encode(value));//urlencode编码
 29                 sb.append("&");
 30             }
 31         }
 32 
 33         String str = sb.toString();
 34         str = str.substring(0, (str.length() - 1)); // 截掉末尾字符“&”
 35 
 36         return requestPost(urlString, str.getBytes("UTF-8"), requestProperties);
 37     }
 38 
 39 
 40     /**
 41      * 发送http请求,并获取返回的数据
 42      * @param urlString
 43      * @param requestData
 44      * @param requestProperties
 45      * @return
 46      * @throws Exception
 47      */
 48     private static byte[] requestPost(String urlString, byte[] requestData, Properties requestProperties)
 49             throws Exception {
 50         byte[] responseData = null;
 51         HttpURLConnection con = null;
 52 
 53         try {
 54             URL url = new URL(urlString);
 55             con = (HttpURLConnection) url.openConnection();
 56 
 57             if ((requestProperties != null) && (requestProperties.size() > 0)) {//设置请求头信息
 58                 for (Map.Entry<Object, Object> entry : requestProperties
 59                         .entrySet()) {
 60                     String key = String.valueOf(entry.getKey());
 61                     String value = String.valueOf(entry.getValue());
 62                     con.setRequestProperty(key, value);
 63                 }
 64             }
 65 
 66             con.setRequestMethod("POST"); // 置为POST方法
 67 
 68             con.setDoInput(true); // 开启输入流
 69             con.setDoOutput(true); // 开启输出流
 70 
 71             // 如果请求数据不为空,输出该数据。
 72             if (requestData != null) {
 73                 DataOutputStream dos = new DataOutputStream(con
 74                         .getOutputStream());
 75                 dos.write(requestData);
 76                 dos.flush();
 77                 dos.close();
 78             }
 79 
 80             int length = con.getContentLength();
 81             // 如果回复消息长度不为-1,读取该消息。
 82             if (length != -1) {
 83                 DataInputStream dis = new DataInputStream(con.getInputStream());
 84                 responseData = new byte[length];
 85                 dis.readFully(responseData);
 86                 dis.close();
 87             }
 88         } catch (Exception e) {
 89             throw e;
 90         } finally {
 91             if (con != null) {
 92                 con.disconnect();
 93             }
 94         }
 95 
 96         return responseData;
 97     }
 98 
 99 
100     /**
101      * url解码
102      *
103      * @param url
104      * @return 解码后的字符串,当异常时返回原始字符串。
105      */
106     private static String decode(String url) {
107         try {
108             return URLDecoder.decode(url, "UTF-8");
109         } catch (UnsupportedEncodingException ex) {
110             return url;
111         }
112     }
113 
114     /**
115      * url编码
116      *
117      * @param url
118      * @return 编码后的字符串,当异常时返回原始字符串。
119      */
120     private static String encode(String url) {
121         try {
122             return URLEncoder.encode(url, "UTF-8");
123         } catch (UnsupportedEncodingException ex) {
124             return url;
125         }
126     }

  发送数据前,需要将数据放入Properties对象中再传入,这是java.util包中的一个工具类,本来主要作用是读取java中以.properties结尾的配置文件,关于这个推荐http://www.cnblogs.com/hyyq/p/7399525.html 。当然,这里完全也可以用Map集合来实现。

  发送数据后,服务端可以通过request.getParameter()方法来获得参数值,也可以通过request.getParameterMap()来获取,它返回的是一个Map<String,String[]>类型的值,因为我们知道表单有 如性别之类的属性是有两个值的。

  小结:通过http模拟表单提交数据,其实和普通的数据提交也是换汤不换药。

  参考:http://blog.163.com/xing_mu_1/blog/static/6614290201031310207158/

以上是关于HTTP通信模拟表单提交数据的主要内容,如果未能解决你的问题,请参考以下文章

如何用C/C++模拟post提交数据,获得http相应。

php curl 模拟post表单向提交数据

c# 模拟表单提交,post form 上传文件大数据内容

Linux curl 模拟form表单提交信息和文件

java 模拟浏览器提交表单后获取新url

利用socket模拟http的混合表单上传(在一个请求中提交表单并上传多个文件)