在java中,特別是java web中,我們經常需要碰到的一個場景是我們需要從服務端去發送http請求,獲取到數據,而不是直接從瀏覽器輸入請求網址獲得相應。比如我們想訪問微信接口,獲取其返回信息。
在這里需要用到java的HttpURLConnection類,此類可以模擬http請求,獲取到的響應以輸入流的形式被程序所取到。現將相關方法整理為工具類。
package com.m_gecko.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.List; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.apache.commons.io.IOUtils; public class HttpUtil { /** * 模擬http的get請求,獲取響應(輸入流),然后把輸入流轉為 * * @param url * @return */ public static String httpGet(String url) { HttpURLConnection connection = null; InputStream response = null; try { connection = (HttpURLConnection) new URL(url).openConnection(); connection.setConnectTimeout(10000); connection.setReadTimeout(10000); response = connection.getInputStream(); if (response != null) { String nextLine = IOUtils.toString(response, "utf-8"); return nextLine; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (response != null) try { response.close(); } catch (IOException e) { e.printStackTrace(); } if (connection != null) { connection.disconnect(); connection = null; } } return null; } /** * 模擬http的post請求,類似上面 * * @param url * @return */ public static String httpPost(String url) { HttpURLConnection connection = null; InputStream response = null; try { connection = (HttpURLConnection) new URL(url).openConnection(); connection.setConnectTimeout(30000); connection.setReadTimeout(30000); // 發送POST請求必須設置如下兩行 connection.setDoOutput(true); connection.setDoInput(true); response = connection.getInputStream(); if (response != null) { String nextLine = IOUtils.toString(response, "utf-8"); return nextLine; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (response != null) try { response.close(); } catch (IOException e) { e.printStackTrace(); } if (connection != null) { connection.disconnect(); connection = null; } } return null; } /** * 向指定URL發送GET方法的請求 * * @param url * 發送請求的URL * @param param * 請求參數,請求參數應該是 name1=value1&name2=value2 的形式。 * @return URL 所代表遠程資源的響應結果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打開和URL之間的連接 HttpURLConnection connection = (HttpURLConnection) realUrl .openConnection(); // 設置通用的請求屬性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立實際的連接 connection.connect(); // 獲取所有響應頭字段 Map<String, List<String>> map = connection.getHeaderFields(); // 遍歷所有的響應頭字段 // for (String key : map.keySet()) { // System.out.println(key + "--->" + map.get(key)); // } // 定義 BufferedReader輸入流來讀取URL的響應 in = new BufferedReader(new InputStreamReader( connection.getInputStream(), "utf-8")); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("發送GET請求出現異常!" + e); e.printStackTrace(); } // 使用finally塊來關閉輸入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 發送POST方法的請求 * * @param url * 發送請求的 URL * @param param * 請求參數,請求參數應該是 name1=value1&name2=value2 的形式。 * @return 所代表遠程資源的響應結果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打開和URL之間的連接 HttpURLConnection conn = (HttpURLConnection) realUrl .openConnection(); // 設置通用的請求屬性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 發送POST請求必須設置如下兩行 conn.setDoOutput(true); conn.setDoInput(true); // 獲取URLConnection對象對應的輸出流 // out = new PrintWriter(conn.getOutputStream()); // // 發送請求參數 // out.print(param); // // flush輸出流的緩沖 // out.flush(); // 定義BufferedReader輸入流來讀取URL的響應 in = new BufferedReader(new InputStreamReader( conn.getInputStream(), "utf-8")); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("發送 POST 請求出現異常!" + e); e.printStackTrace(); } // 使用finally塊來關閉輸出流、輸入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } /** * 向指定 URL 發送POST方法的請求 * * @param url * 發送請求的 URL * @param params * 請求的參數集合 * @return 遠程資源的響應結果 */ public static String sendPost(String url, Map<String, String> params) { OutputStreamWriter out = null; BufferedReader in = null; StringBuilder result = new StringBuilder(); try { URL realUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) realUrl .openConnection(); // 發送POST請求必須設置如下兩行 conn.setDoOutput(true); conn.setDoInput(true); // POST方法 conn.setRequestMethod("POST"); // 設置通用的請求屬性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.connect(); // 獲取URLConnection對象對應的輸出流 out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); // 發送請求參數 if (params != null) { StringBuilder param = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (param.length() > 0) { param.append("&"); } param.append(entry.getKey()); param.append("="); param.append(entry.getValue()); // System.out.println(entry.getKey()+":"+entry.getValue()); } System.out.println("param:" + param.toString()); out.write(param.toString()); } // flush輸出流的緩沖 out.flush(); // 定義BufferedReader輸入流來讀取URL的響應 in = new BufferedReader(new InputStreamReader( conn.getInputStream(), "UTF-8")); String line; while ((line = in.readLine()) != null) { result.append(line); } } catch (Exception e) { e.printStackTrace(); } // 使用finally塊來關閉輸出流、輸入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result.toString(); } /** * url編碼 * * @param str * @param charset * @return * @throws UnsupportedEncodingException */ public static String urlEncoder(String str, String charset) throws UnsupportedEncodingException { if (str == null) { str = ""; } String result = URLEncoder.encode(str, charset); return result; } /** * 發送https請求 * * @param requestUrl * 請求地址 * @param requestMethod * 請求方式(GET、POST) * @param outputStr * 提交的數據 * @return 返回微信服務器響應的信息 */ public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) { try { // 創建SSLContext對象,並使用我們指定的信任管理器初始化 TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 從上述SSLContext對象中得到SSLSocketFactory對象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(ssf); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); // 設置請求方式(GET/POST) conn.setRequestMethod(requestMethod); conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); // 當outputStr不為null時向輸出流寫數據 if (null != outputStr) { OutputStream outputStream = conn.getOutputStream(); // 注意編碼格式 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 從輸入流讀取返回內容 InputStream inputStream = conn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader( inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader( inputStreamReader); String str = null; StringBuffer buffer = new StringBuffer(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } // 釋放資源 bufferedReader.close(); inputStreamReader.close(); inputStream.close(); inputStream = null; conn.disconnect(); return buffer.toString(); } catch (ConnectException ce) { ce.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } }
其中https請求所需要的信任管理器實現了X509TrustManager接口。
package com.m_gecko.util; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; /** * 信任管理器 * @author xdx */ public class MyX509TrustManager implements X509TrustManager { // 檢查客戶端證書 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } // 檢查服務器端證書 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } // 返回受信任的X509證書數組 public X509Certificate[] getAcceptedIssuers() { return null; } }