使用Java原生API编写发送HTTP_POST请求的工具类

  1. package com.jadyer.util;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.InputStream;  
  5. import java.io.OutputStream;  
  6. import java.io.UnsupportedEncodingException;  
  7. import java.net.HttpURLConnection;  
  8. import java.net.URL;  
  9. import java.net.URLEncoder;  
  10. import java.util.HashMap;  
  11. import java.util.List;  
  12. import java.util.Map;  
  13.   
  14. /** 
  15.  * 使用Java原生API编写发送HTTP_POST请求的工具类 
  16.  * @see ------------------------------------------------------------------------------------------ 
  17.  * @see 与之类似的还有一个HttpClientUtil工具类 
  18.  * @see 地址为http://blog.csdn.net/jadyer/article/details/8087960 
  19.  * @see ------------------------------------------------------------------------------------------ 
  20.  * @see 本方法的美中不足是:服务器返回500时,它会直接抛出类似下面的异常 
  21.  * @see java.io.IOException: Server returned HTTP response code: 500 for URL: http://xxxx/xxxx 
  22.  * @see 原因很简单:因为这里用到的是SUN提供的基于HTTP协议的框架实现 
  23.  * @see ------------------------------------------------------------------------------------------ 
  24.  * @see 个人更推荐使用Socket发送HTTP请求 
  25.  * @see 例子见http://blog.csdn.net/jadyer/article/details/8788272 
  26.  * @see ------------------------------------------------------------------------------------------ 
  27.  * @create Mar 4, 2013 2:47:57 PM 
  28.  * @editor Apr 4, 2013 10:02:18 AM 
  29.  * @author 玄玉<http://blog.csdn.net/jadyer> 
  30.  */  
  31. public class NativeHTTPUtil {  
  32.     private NativeHTTPUtil(){}  
  33.       
  34.     /** 
  35.      * 发送HTTP_POST请求 
  36.      * @see 本方法默认的连接和读取超时均为30秒 
  37.      * @see 请求参数含有中文时,亦可直接传入本方法中,本方法内部会自动根据reqCharset参数进行<code>URLEncoder.encode()</code> 
  38.      * @see 解码响应正文时,默认取响应头[Content-Type=text/html; charset=GBK]字符集,若无Content-Type,则使用UTF-8解码 
  39.      * @param reqURL     请求地址 
  40.      * @param reqParams  请求正文数据 
  41.      * @param reqCharset 请求报文的编码字符集(主要针对请求参数值含中文而言) 
  42.      * @return respCode-->HTTP响应码,respBody-->HTTP响应报文体,respMsg-->HTTP响应完整报文 
  43.      */  
  44.     public static Map<String, String> sendPostRequest(String reqURL, Map<String, String> reqParams, String reqCharset) {  
  45.         StringBuilder reqData = new StringBuilder();  
  46.         for (Map.Entry<String, String> entry : reqParams.entrySet()) {  
  47.             try {  
  48.                 reqData.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), reqCharset)).append("&");  
  49.             } catch (UnsupportedEncodingException e) {  
  50.                 System.out.println("编码字符串[" + entry.getValue() + "]时发生异常:系统不支持该字符集[" + reqCharset + "]");  
  51.                 reqData.append(entry.getKey()).append("=").append(entry.getValue()).append("&");  
  52.             }  
  53.         }  
  54.         if (reqData.length() > 0) {  
  55.             reqData.setLength(reqData.length() - 1); //删除最后一个&符号  
  56.         }  
  57.         return sendPostRequest(reqURL, reqData.toString(), reqCharset);  
  58.     }  
  59.       
  60.       
  61.     /** 
  62.      * 发送HTTP_POST请求 
  63.      * @see you can see {@link NativeHTTPUtil#sendPostRequest(String, Map, String)} 
  64.      * @see 注意:若欲直接调用本方法,切记请求参数值含中文时,一定要对该参数值<code>URLEncoder.encode(value, reqCharset)</code> 
  65.      * @see 注意:这里只是对key=value中的'value'进行encode,而非'key='..encode完毕后,再组织成key=newValue传给本方法 
  66.      */  
  67.     public static Map<String, String> sendPostRequest(String reqURL, String reqData, String reqCharset) {  
  68.         Map<String, String> respMap = new HashMap<String, String>();  
  69.         HttpURLConnection httpURLConnection = null;  
  70.         OutputStream out = null//写  
  71.         InputStream in = null;   //读  
  72.         String respBody = null;  //HTTP响应报文体  
  73.         String respCharset = "UTF-8";  
  74.         try {  
  75.             URL sendUrl = new URL(reqURL);  
  76.             httpURLConnection = (HttpURLConnection)sendUrl.openConnection();  
  77.             httpURLConnection.setDoInput(true);    //true表示允许获得输入流,读取服务器响应的数据,该属性默认值为true  
  78.             httpURLConnection.setDoOutput(true);   //true表示允许获得输出流,向远程服务器发送数据,该属性默认值为false  
  79.             httpURLConnection.setUseCaches(false); //禁止缓存  
  80.             httpURLConnection.setReadTimeout(30000);    //30秒读取超时  
  81.             httpURLConnection.setConnectTimeout(30000); //30秒连接超时  
  82.             httpURLConnection.setRequestMethod("POST");  
  83.               
  84.             out = httpURLConnection.getOutputStream();  
  85.             out.write(reqData.getBytes());  
  86.             out.flush(); //发送数据  
  87.               
  88.             /** 
  89.              * 获取HTTP响应头 
  90.              * @see URLConnection类提供了读取远程服务器响应数据的一系列方法 
  91.              * @see getHeaderField(String name)可以返回响应头中参数name指定的属性的值 
  92.              * @see 注意:经过我的测试,此处获取到头属性的顺序与服务器响应的真实头属性顺序或可不一致 
  93.              * @see 注意:测试时,我让服务器返回的头属性中,Content-Type排在第一个,Content-Length排在第二个 
  94.              * @see 注意:结果在此处获取到的响应头属性中,Content-Length排在第一个,Content-Type排在第二个 
  95.              */  
  96.             StringBuilder respHeader = new StringBuilder();  
  97.             Map<String, List<String>> headerFields = httpURLConnection.getHeaderFields();  
  98.             for(Map.Entry<String, List<String>> entry : headerFields.entrySet()){  
  99.                 StringBuilder sb = new StringBuilder();  
  100.                 for(int i=0; i<entry.getValue().size(); i++){  
  101.                     sb.append(entry.getValue().get(i));  
  102.                 }  
  103.                 if(null == entry.getKey()){  
  104.                     respHeader.append(sb.toString());  
  105.                 }else{  
  106.                     respHeader.append(entry.getKey()).append(": ").append(sb.toString());  
  107.                 }  
  108.                 respHeader.append("\r\n");  
  109.             }  
  110.               
  111.             /** 
  112.              * 获取Content-Type中的charset值 
  113.              * @see 如Content-Type: text/html; charset=GBK 
  114.              */  
  115.             String contentType = httpURLConnection.getContentType();  
  116.             if(null!=contentType && contentType.toLowerCase().contains("charset")){  
  117.                 respCharset = contentType.substring(contentType.lastIndexOf("=") + 1);  
  118.             }  
  119.               
  120.             /** 
  121.              * 获取HTTP响应正文 
  122.              * @see --------------------------------------------------------------------------------------------- 
  123.              * @see SUN提供了基于HTTP协议的框架实现,不过,这些实现类并没有在JDK类库中公开,它们都位于sun.net.www包或者其子包中 
  124.              * @see 并且,URLConnection具体子类(HttpURLConnection类)的getInputStream()方法仅仅返回响应正文部分的输入流 
  125.              * @see HTTP响应结果包括HTTP响应码,响应头和响应正文3部分,获得输入流后,就能读取服务器发送的响应正文 
  126.              * @see ---------------------------------------------------------------------------------------------- 
  127.              * @see 使用httpURLConnection.getContentLength()时,要保证服务器给返回Content-Length头属性 
  128.              * @see byte[] byteDatas = new byte[httpURLConnection.getContentLength()]; 
  129.              * @see httpURLConnection.getInputStream().read(byteDatas); 
  130.              * @see respBody = new String(byteDatas, respCharset); 
  131.              * @see ---------------------------------------------------------------------------------------------- 
  132.              * @see in = httpURLConnection.getInputStream(); 
  133.              * @see byte[] byteDatas = new byte[in.available()]; 
  134.              * @see 关于InputStream.available()说明如下,更详细说明见JDK API DOC 
  135.              * @see 有些InputStream的实现将返回流中的字节总数,但也有很多实现不会这样做 
  136.              * @see 试图使用in.available()方法的返回值分配缓冲区,以保存此流所有数据的做法是不正确的 
  137.              * @see ---------------------------------------------------------------------------------------------- 
  138.              */  
  139.             in = httpURLConnection.getInputStream();  
  140.             ByteArrayOutputStream buffer = new ByteArrayOutputStream();  
  141.             byte[] buff = new byte[1024];  
  142.             int len = -1;  
  143.             while((len=in.read(buff)) != -1){  
  144.                 buffer.write(buff, 0, len);  
  145.             }  
  146.             respBody = buffer.toString(respCharset);  
  147.               
  148.             //使用httpURLConnection.getResponseMessage()可以获取到[HTTP/1.0 200 OK]中的[OK]  
  149.             respMap.put("respCode", String.valueOf(httpURLConnection.getResponseCode()));  
  150.             respMap.put("respBody", respBody);  
  151.             respMap.put("respMsg", respHeader.toString() + "\r\n" + respBody);  
  152.             return respMap;  
  153.         } catch (Exception e) {  
  154.             System.out.println("与[" + reqURL + "]通信异常,堆栈信息如下");  
  155.             e.printStackTrace();  
  156.             return respMap;  
  157.         } finally {  
  158.             if (out != null) {  
  159.                 try {  
  160.                     out.close();  
  161.                 } catch (Exception e) {  
  162.                     System.out.println("关闭输出流时发生异常,堆栈信息如下");  
  163.                     e.printStackTrace();  
  164.                 }  
  165.             }  
  166.             if (in != null) {  
  167.                 try {  
  168.                     in.close();  
  169.                 } catch (Exception e) {  
  170.                     System.out.println("关闭输入流时发生异常,堆栈信息如下");  
  171.                     e.printStackTrace();  
  172.                 }  
  173.             }  
  174.             if (httpURLConnection != null) {  
  175.                 httpURLConnection.disconnect();  
  176.                 httpURLConnection = null;  
  177.             }  
  178.         }  
  179.     }  
  180. }  


下面是测试代码

[java]  view plain  copy
 
 
  1. public static void main(String[] args) {  
  2.     Map<String, String> params = new HashMap<String, String>();  
  3.     params.put("merNo""301100100001630");  
  4.     params.put("signType""MD5");  
  5.     params.put("merBindAgrNo""00003018007000006450000013866742");  
  6.     params.put("interfaceVersion""1.0.0.0");  
  7.     params.put("amount""1000");  
  8.     params.put("orderDate""20120823");  
  9.     params.put("orderNo""UDP1208230917531231111");  
  10.     params.put("merReqTime""20120823091802");  
  11.     params.put("goodsDesc""为号码交费充值元");  
  12.     params.put("goodsName""中国联通交费充值");  
  13.     params.put("userIdeMark""3");  
  14.     params.put("bankAgrMode""9");  
  15.     params.put("signMsg""3ced24a118461043901d47815e6905a8");  
  16.     Map<String, String> respMap = sendPostRequest("http://127.0.0.1/tra/bind/payment.htm", params, "UTF-8");  
  17.     System.out.println("=============================================================================");  
  18.     System.out.println("HTT响应码如下");  
  19.     System.out.println(respMap.get("respCode"));  
  20.     System.out.println("=============================================================================");  
  21.     System.out.println("HTT响应正文如下");  
  22.     System.out.println(respMap.get("respBody"));  
  23.     System.out.println("=============================================================================");  
  24.     System.out.println("HTTP响应完整报文如下");  
  25.     System.out.println(respMap.get("respMsg"));  
  26.     System.out.println("=============================================================================");  
  27. }  

下面是控制台输出

[java]  view plain  copy
 
 
  1. //控制台输出如下  
  2. //=============================================================================  
  3. //  HTT响应码如下  
  4. //  200  
  5. //  =============================================================================  
  6. //  HTT响应正文如下  
  7. //  interfaceVersion=1.0.0.0  
  8. //  merReqTime=  
  9. //  payJournl=  
  10. //  amount=  
  11. //  orderNo=UDP1208230917531231111  
  12. //  orderTime=20120823  
  13. //  payBankNo=  
  14. //  bankAccNo=  
  15. //  bankAccName=  
  16. //  transRet=ILLEGAL_MERCHANT_NO  
  17. //  resultDis=商户签名key查询失败致使无法验签  
  18. //  acceptDate=  
  19. //  acceptTime=  
  20. //  signType=MD5  
  21. //  signMsg=29a312ab08b7273d7500a960c8c86b73  
  22. //  =============================================================================  
  23. //  HTTP响应完整报文如下  
  24. //  HTTP/1.1 200 OK  
  25. //  Content-Length: 289  
  26. //  Content-Type: text/html; charset=GBK  
  27. //  
  28. //  interfaceVersion=1.0.0.0  
  29. //  merReqTime=  
  30. //  payJournl=  
  31. //  amount=  
  32. //  orderNo=UDP1208230917531231111  
  33. //  orderTime=20120823  
  34. //  payBankNo=  
  35. //  bankAccNo=  
  36. //  bankAccName=  
  37. //  transRet=ILLEGAL_MERCHANT_NO  
  38. //  resultDis=商户签名key查询失败致使无法验签  
  39. //  acceptDate=  
  40. //  acceptTime=  
  41. //  signType=MD5  
  42. //  signMsg=29a312ab08b7273d7500a960c8c86b73  
  43. //  =============================================================================  
  44. //  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值