①HttpURLConnection通過報文提交


在進行短信發送的接口,因廠家不同,有的廠家會采用報文的格式進行短信請求的發送與接收。本文主要介紹利用HttpURLConnection進行短信報文的請求與響應。

一般的url請求分為兩種,一種是GET,一種是POST:
1.GET請求的參數是放在url后面拼接的,請求大小有限制,具體多少大家可以自行去百度,在這里就不多說了
2.POST請求參數是放在HTTP請求的正文里的,可傳輸的內容遠大於GET請求,而且理論上來說POST請求是沒有大小限制的,所以使用POST請求較多
一般正常的請求,get參數會顯示在地址欄上,參數很容易被獲取,安全性也較低,所以使用POST請求會比較好

HttpURLConnection有兩種簡單的設置請求頭的方法

setRequestProperty(key,value)
addRequestProperty(key,value)

setRequestProperty和addRequestProperty的區別就是,setRequestProperty會覆蓋已經存在的key的所有values,有清零重新賦值的作用。而addRequestProperty則是在原來key的基礎上繼續添加其他value。

發送報文格式如圖所示:

短信發送:

   try {
 String postXml = "<?xml version='1.0' encoding='UTF-8'?>"; postXml = postXml + "<mtpacket>"; postXml = postXml + "<cpid>" +ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_CPID)+ "</cpid>"; postXml = postXml + "<userpass>" + ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_USERPASS) + "</userpass>"; postXml = postXml + "<port>" + ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_PORT)+ "</port>"; postXml = postXml + "<respDataType>XML</respDataType>"; postXml = postXml + "<cpmid>" + ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_CPMID)+ "</cpmid>"; postXml = postXml + "<flag>1</flag>"; postXml = postXml + "<mobile><![CDATA[" + mobile + "]]></mobile>"; postXml = postXml + "<message><![CDATA[" + new String(content.getBytes(), "utf-8") + "]]></message>"; postXml = postXml + "</mtpacket>"; logger.info("發送url:{},發送內容:{}",ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_POSTURL), postXml);
     //1.連接的URL URL url
= new URL(ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_POSTURL));
     //2.這個地方的conn是根據請求協議(此處是http協議)生成的URLConnection類的子類HttpURLConnection
//所以將其轉化為HttpURLConnection類,以便使用HttpURLConnection更過的API
HttpURLConnection conn
= (HttpURLConnection)url.openConnection();
//3.POST可以更好的傳參 conn.setRequestMethod(
"POST");
    //4.是否使用緩存,Post 請求不能使用緩存 conn.setUseCaches(
false);
         //5.設置之后可以向服務端寫入數據、、可以使用conn.getOutputStream().write()
     // 可以傳輸參數,POST請求數據放在正文內,所以需要開啟傳參
conn.setDoOutput(
true);
         //6.http讀取數據
         // 默認是true,所以可以一般的請求都可以獲取數據
         urlConnection.setDoInput(true);
     //7.設置請求頭
conn.setRequestProperty(
"Content-type", "text/xml;charset=UTF-8");
   //8.輸出流,進行傳參,所有數據放在這里 OutputStreamWriter
out = new OutputStreamWriter(conn.getOutputStream());
       //9.寫入參數內容
out.write(postXml);
       //10.刷新輸出流,把所有的數據流數據都傳輸過去
out.flush();
         //11.關閉輸出流
out.close();

}catch (Exception e){
e.printStackTrace();
}

 接收短信報文:

接收短信代碼:

 if (conn.getResponseCode() != 200) { logger.info("發送失敗:返回狀態:" + conn.getResponseCode()); } String result = "";
         //獲取輸入流,這段是正式請求,會把所有的設置和參數以http方式進行請求 BufferedReader
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "GBK")); String line; while ((line = in.readLine()) != null) { result = result + line + "\n"; } in.close(); String re = result.trim().replaceAll("'", "\"");
         //打印獲取的數據 logger.info(
"請求返回:" + re); if (!re.contains("<respCode>0</respCode>")) { logger.info("發送失敗:返回:" + re); }

完整示例代碼:

 @Override public void sendSms(String mobile, String content, Map<String, Object> params) { try { String postXml = "<?xml version='1.0' encoding='UTF-8'?>"; postXml = postXml + "<mtpacket>"; postXml = postXml + "<cpid>" +ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_CPID)+ "</cpid>"; postXml = postXml + "<userpass>" + ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_USERPASS) + "</userpass>"; postXml = postXml + "<port>" + ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_PORT)+ "</port>"; postXml = postXml + "<respDataType>XML</respDataType>"; postXml = postXml + "<cpmid>" + ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_CPMID)+ "</cpmid>"; postXml = postXml + "<flag>1</flag>"; postXml = postXml + "<mobile><![CDATA[" + mobile + "]]></mobile>"; postXml = postXml + "<message><![CDATA[" + new String(content.getBytes(), "utf-8") + "]]></message>"; postXml = postXml + "</mtpacket>"; logger.info("發送url:{},發送內容:{}",ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_POSTURL), postXml); URL url = new URL(ZkjnSmsConfig.getConfigValue(ZkjnSmsConfig.SMS_ZKJN_POSTURL)); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("POST"); conn.setUseCaches(false); conn.setDoOutput(true); conn.setRequestProperty("Content-type", "text/xml;charset=UTF-8"); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); out.write(postXml); out.flush(); out.close(); if (conn.getResponseCode() != 200) { logger.info("發送失敗:返回狀態:" + conn.getResponseCode()); } String result = ""; BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "GBK")); String line; while ((line = in.readLine()) != null) { result = result + line + "\n"; } in.close(); String re = result.trim().replaceAll("'", "\""); logger.info("請求返回:" + re); if (!re.contains("<respCode>0</respCode>")) { logger.info("發送失敗:返回:" + re); } }catch (Exception e){ e.printStackTrace(); } }

注意事項:

1.set一些設置的時候必須在connection之前,如果在connection之后這些set都沒有效果了
2.post請求的正文是通過outputStream流寫入的,但是在這並沒有真正的去發送請求,只是放在了內存緩沖區,只有當getInputStream()調用的時候才真正的去請求
3.設置超時,防止網絡異常的情況下,可能會導致程序僵死而不繼續往下執行 

//超時設置必須在connection之前
urlConnection.setConnectTimeout(5 * 1000);// 5秒連接超時
urlConnection.setReadTimeout(5 * 1000);// 5秒獲取內容超時

4.添加請求頭的時候如果有中文,就有可能造成中文亂碼這時候可以使用這個方法

// 參數進行encode(編碼),防止中文亂碼
urlConnection.setRequestProperty("test", URLEncoder.encode("一個測試請求頭", "UTF-8"));

對某個參數進行URLEncoder.encode,服務端獲取參數之后再通過URLDecoder.decode一下就可以獲得完整的中文了 

5.如果環境是采用GBK編碼,而短信是采用utf-8中文英文數字組合的方式組織的,這個時候要注意。要做一下操作

首先要將中文字符進行轉換, 

 postXml = postXml + "<message><![CDATA[" + new String(content.getBytes("UTF-8"),"UTF-8") + "]]></message>"

其次在進行流輸出的時候,要設定輸出字符,否則在轉換的時候,容易出現,字符不匹配出現亂碼的問題【環境GBK,流輸出默認是采用環境編碼的】:

 OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(),Charset.forName("UTF-8"));

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM