1.此例子看考:https://blog.csdn.net/Jane_Liee/article/details/78527859,代碼沒復制全,因為只為解釋。
java.net包是用於網絡連接使用的。她的原理是:通過本地請求信息將本地tcp套接字和目標地套接字連接起來。一旦建立連接,雙方都會對自己的套接字監聽,一旦有數據進入會立刻發現並處理。所以,當我們的請求信息被寫入到對方的套接字中時對方會立即拿到並通過我們連接寫入到我們的套接字中,此時我們會立即拿到對方寫入(響應)的信息。從對方將信息寫入到我們的套接字后便主動斷開連接,我們也會隨之斷開連接。這就是底層的交互方式,是用c語言寫的,jdk進過對這些底層的方法進行封裝后提供給我們的就是java.net包下的封裝。
下列方法的流程就是:先通過URL打開雙方的連接(著名的3次握手就是這時候做的) -> 填寫請求數據 -> 將數據刷新到對方的套接字中 -> 對方收到請求信息后 -> 再將響應返回到請求的套接字中,然后關閉套接字直接的連接(即釋放對方的地址內容) -> 此時請求放從自己的套接字中拿到了響應信息,也釋放了自己套接字中對方的套接字信息。這就是一次完整的http請求
簡單來說就是:我將我的請求信息給我的套接字,然后我的套接字將請求信息寫入對方的套接字,之后對方又將響應的信息寫入到我的套接字,然后雙方關閉連接。
所以有了以上的定論:那么下列代碼中就很好解釋了,URL開啟連接后再賦值最后刷新到對方去,然后等待對方刷新到我們這兒來后就有讀取。其中用到的conn.getOutputStream()就是往對方套接字中寫數據的流(序列化),之后的out.flush();就是將緩存中的請求數據都刷新到對方套接字中去。在刷新到對方套接字中去后會主動等待對方回來,在conn.getInputStream()的時候對方消息已經回來了並且對方也已經關閉連接了。如果對方沒消息也會回來一個異常消息。此時就可以通過輸入流(反序列化)conn.getInputStream()來讀取本地套接字中對方返回的內容了。
1.示例1:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import net.sf.json.JSONObject; public static JSONObject sendPost(String url,Map<String, Object> paramMap){ JSONObject jsonObj = null; if(url != "https:/Your URL!"){ //獲取token,這里是OAuth 2.0認證 paramMap.put("access_token", getToken()); } try { URL realUrl = new URL(url); URLConnection conn = realUrl.openConnection(); //指定客戶端能夠接收的內容類型 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive");//設置連接的狀態 //User-Agent的內容包含發出請求的用戶信息 conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); conn.setRequestProperty("Charset", "UTF-8"); conn.setDoOutput(true); conn.setDoInput(true); PrintWriter out = new PrintWriter(conn.getOutputStream()); String param = mapToParam(paramMap); out.print(param); out.flush(); BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; String str = ""; while ((line = in.readLine()) != null) { str += line; } jsonObj = JSONObject.fromObject(str); } catch (MalformedURLException e) { System.err.println("URL協議、格式或者路徑錯誤!" + e); e.printStackTrace(); } catch (IOException e) { System.err.println("URL連接失敗!" + e); e.printStackTrace(); } catch (Exception e) { System.err.println("發送 POST 請求出現異常!" + e); e.printStackTrace(); } return jsonObj; }
2.示例2:這個是apache提供的庫:一樣的流程和功能,只是提供的更加優雅而已,但是越優雅的東西限制就會越大,大到你無法改動或難於理解底層,其實他這個也一樣:我們可以看到上面URL做的事情在這換成了HttpClient,而請求方式,消息頭參數也都提供了專門的方法:請求方法:PostMethod ,請求參數:RequestEntity ,上面的刷新(序列化)對應這邊的httpClient.executeMethod(post);最后的讀取(反序列化)和上面差不多
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSONObject; public static JSONObject post(String url, JSONObject requestInfo) throws HttpException, IOException { String path = "/api/jobinfo/save"; String targetUrl = url + path; HttpClient httpClient = new HttpClient(); PostMethod post = new PostMethod(targetUrl); RequestEntity requestEntity = new StringRequestEntity(requestInfo.toString(), "application/json", "utf-8"); post.setRequestEntity(requestEntity); httpClient.executeMethod(post); JSONObject result = new JSONObject(); result = getJsonObject(post, result); return result; } private static JSONObject getJsonObject(HttpMethod get, JSONObject result) throws IOException { InputStream inputStream = get.getResponseBodyAsStream(); BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer stringBuffer = new StringBuffer(); String str = ""; while ((str = br.readLine()) != null) { stringBuffer.append(str); } if (get.getStatusCode() == 200) { result = JSONObject.parseObject(stringBuffer.toString()); } else { try { result = JSONObject.parseObject(stringBuffer.toString()); } catch (Exception e) { result.put("error", stringBuffer.toString()); } } br.close(); inputStream.close(); return result; }
示例3:apache提供
import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; private static String sendPostRequest(String reqURL, String json, String encoding, String authorization) { HttpPost httpPost = new HttpPost(reqURL); CloseableHttpClient httpClient = HttpClientUtil.getConnection(); HttpResponse response = null; String result = ""; try { StringEntity entity = new StringEntity(json, encoding); entity.setContentType("application/json"); httpPost.setEntity(entity); httpPost.setHeader("Authorization", authorization.trim()); response = httpClient.execute(httpPost); result = EntityUtils.toString(response.getEntity(), encoding); } catch (Exception e) { log.error("請求通信[" + reqURL + "]時偶遇異常,堆棧軌跡如下", e); } return result; }
示例4:okhttp3提供:請求流程一樣,原理也一樣,這種編碼方式到比較好,自由操作度高,沒有acache封裝的那么狠,但是需要了解http請求中的每個字段方可操作,越熟悉越厲害嘛。這個里面還提供了用於http請求的線程池。這是很好的設計。
import java.util.concurrent.TimeUnit; import com.google.common.collect.Maps; import okhttp3.ConnectionPool; import okhttp3.ConnectionSpec; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; private static ConnectionPool pool = null; static { pool = new ConnectionPool(100, 20, TimeUnit.MINUTES); } public static String sendGetBindPlayer(String cookie, String url) throws IOException { OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(3000L, TimeUnit.MILLISECONDS) .readTimeout(3000L, TimeUnit.MILLISECONDS) .connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS)) .connectionPool(pool).build(); Request.Builder requestBuilder = new Request.Builder().url(url).addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 qblink tgp_daemon.exe QBCore/3.43.812.400 QQBrowser/9.0.2524.400") .addHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.5;q=0.4") .addHeader("Accept", "image/sharpp,*/*"); Map<String, List<String>> map = getMap(cookie); for (String key : map.keySet()) { for (String value : map.get(key)) { requestBuilder.addHeader(key, value); } } Request request = requestBuilder.build(); Response response = okHttpClient.newCall(request).execute(); if (response.isSuccessful()) { String result = response.body().string();// 結果 return result; } else { throw new IOException("Unexpected code " + response); } }