【封裝】非同步HttpURLConnection網路訪問
阿新 • • 發佈:2018-11-26
知識擴充套件:
主體:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Scanner;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* Asynchronous http requests implementation.
*/
public class AsyncHttpURLConnection {
private static final int HTTP_TIMEOUT_MS = 8000;
private static final String HTTP_ORIGIN = AppRTC_Common.HTTP_ORIGIN;
private final String method;
private final String url;
private final String message;
private final AsyncHttpEvents events;
private String contentType;
private String TAG = "AsyncHttp";
/**
* 定義回撥的介面
* Http requests callbacks.
*/
public interface AsyncHttpEvents {
void onHttpError(String errorMessage);
void onHttpComplete(String response);
}
//靜態程式碼塊。
//重要:關於靜態程式碼塊的執行順序問題,請關注本博文開頭的相關連結。
static {
//忽略安全證書的問題,即https
disableSslVerification();
}
/**
* 建構函式
*
* @param method
* @param url
* @param message
* @param events
*/
public AsyncHttpURLConnection(String method, String url, String message, AsyncHttpEvents events) {
this.method = method;
this.url = url;
this.message = message;
this.events = events;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public void send() {
Runnable runHttp = new Runnable() {
public void run() {
sendHttpMessage();
}
};
new Thread(runHttp).start();
}
private void sendHttpMessage() {
try {
HttpURLConnection connection; //= (HttpURLConnection) new URL(url).openConnection();
URL Url = new URL(url);
connection = (HttpURLConnection) Url.openConnection();
byte[] postData = new byte[0];
if (message != null) {
postData = message.getBytes("UTF-8");
}
connection.setRequestMethod(method);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setConnectTimeout(HTTP_TIMEOUT_MS);
connection.setReadTimeout(HTTP_TIMEOUT_MS);
// TODO(glaznev) - query request origin from pref_room_server_url_key preferences.
connection.addRequestProperty("origin", HTTP_ORIGIN);
/**
* 為了防止CSRF的攻擊,我們建議修改瀏覽器在傳送POST請求的時候加上一個Origin欄位.
* 這個Origin欄位主要是用來標識出最初請求是從哪裡發起的。
* 如果瀏覽器不能確定源在哪裡,那麼在傳送的請求裡面Origin欄位的值就為空。
*/
boolean doOutput = false;
if (method.equals("POST")) {
doOutput = true;
connection.setDoOutput(true);
connection.setFixedLengthStreamingMode(postData.length);
}
if (contentType == null) {
connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
} else {
connection.setRequestProperty("Content-Type", contentType);
}
// Send POST request.
if (doOutput && postData.length > 0) {
OutputStream outStream = connection.getOutputStream();
outStream.write(postData);
outStream.close();
}
// Get response.
int responseCode = connection.getResponseCode();
//Log.e(TAG, "responseCode:" + responseCode);
if (responseCode != 200) {
events.onHttpError("Non-200 response to " + method + " to URL: " + url + " : "
+ connection.getHeaderField(null));
connection.disconnect();
return;
}
InputStream responseStream = connection.getInputStream();
String response = drainStream(responseStream);
responseStream.close();
connection.disconnect();
events.onHttpComplete(response);
} catch (SocketTimeoutException e) {
events.onHttpError("HTTP " + method + " to " + url + " timeout");
} catch (IOException e) {
events.onHttpError("HTTP " + method + " to " + url + " error: " + e.getMessage());
}
}
// Return the contents of an InputStream as a String.
private static String drainStream(InputStream in) {
Scanner s = new Scanner(in).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
/**
* 忽略安全證書
*/
private static void disableSslVerification() {
try {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
}
使用
- 傳送POST請求
//POST請求中,表單的具體內容
JSONObject json = new JSONObject();
jsonPut(json, "type", "text");
jsonPut(json, "content", "balabala");
jsonPut(json, "id", "123");
String method="POST";
String myUrl="www.balabalabala.com/query";
AsyncHttpURLConnection httpURLConnection = new AsyncHttpURLConnection(method,
myUrl,
json.toString(),
new AsyncHttpURLConnection.AsyncHttpEvents() {
@Override
public void onHttpError(String errorMessage) {
//Log.e(TAG, "網路連線失敗:" + errorMessage);
//System.out.println("網路連線失敗:" + errorMessage);
}
@Override
public void onHttpComplete(String response) {
//Log.e(TAG,"網路連線成功:"+response);
//System.out.println("網路連線成功:"+response);
}
});
httpURLConnection.send();
輔助作用的類
// Put a |key|->|value| mapping in |json|.
public static void jsonPut(JSONObject json, String key, Object value) {
try {
json.put(key, value);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
抓住Demo一隻:
為了方便以後呼叫,本人已經將上述方法封裝到了.aar檔案中。以後呼叫時,只需要匯入第三方包即可。
歡迎大家補充交流。