日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HttpUrlConnection get和post简单实现(疑惑解决)

發布時間:2025/7/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HttpUrlConnection get和post简单实现(疑惑解决) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

近期研究微信的公眾平臺開發。須要和微信的server進行數據讀取,簡單研究了下jdk自帶的HttpUrlConnection類(URLConnection的子類),簡單實現了一下微信的access_token獲取。

獲取微信access_token的地址:微信地址

該地址是get方法請求就可以。先貼代碼,doGet:

private final String ACCESS_TOKEN_WEIXIN = "https://api.weixin.qq.com/cgi-bin/token";public String doGet(String grantType, String appId, String secret){String url = ACCESS_TOKEN_WEIXIN+"?grant_type="+grantType+"&appid="+appId+"&secret="+secret;HttpURLConnection conn = null;InputStream is = null;InputStreamReader reader = null;BufferedReader br = null;String str = "";try {URL weiUrl = new URL(url);conn = (HttpURLConnection)weiUrl.openConnection();conn.setRequestProperty("connection", "Keep-Alive");conn.connect();is = conn.getInputStream();reader = new InputStreamReader(is, "UTF-8");br = new BufferedReader(reader);String readLine = "";while((readLine=br.readLine())!=null){str+=readLine+"\n";}} catch (Exception e) {e.printStackTrace();}finally{try{if(br!=null){br.close();}if(conn!=null){conn.disconnect();}}catch(Exception e1){e1.printStackTrace();}}return str;}
我將InputStream流和InputStreamReader流都單獨定義引用是為了測試流關閉的問題,最后僅僅關閉最外層流,由于外層流關閉的時候就將包裹的流一并關閉了。見以下的BufferedReader類的close方法:

public void close() throws IOException {synchronized (lock) {if (in == null)return;in.close();in = null;cb = null;}}當中,in就是包裹的流。


以下貼post方法的代碼。然后綜合比較一下,代碼:

public String doPost(String grantType, String appId, String secret){HttpURLConnection conn = null;InputStream is = null;InputStreamReader reader = null;BufferedReader br = null;String str = "";try {URL url = new URL(ACCESS_TOKEN_WEIXIN);conn = (HttpURLConnection)url.openConnection();conn.setRequestMethod("POST");conn.setDoOutput(true);//默覺得false的,所以須要設置conn.setUseCaches(false);conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");conn.connect();OutputStream outStream = conn.getOutputStream();DataOutputStream out = new DataOutputStream(outStream);String params = "grant_type="+grantType+"&appid="+appId+"&secret="+secret;out.writeBytes(params);out.close();is = conn.getInputStream();reader = new InputStreamReader(is, "UTF-8");br = new BufferedReader(reader);String readLine = "";while((readLine=br.readLine())!=null){str+=readLine+"\n";}} catch (Exception e) {e.printStackTrace();}finally{try{if(br!=null){br.close();}if(conn!=null){conn.disconnect();}}catch(Exception e1){e1.printStackTrace();}}return str;}
兩相比較:

1.思路是一樣的:首先建立鏈接對象(URL)->由鏈接對象得到代理對象(HttpUrlConnection)->設置一些鏈接參數->啟動鏈接通道(conn.connect();)->進行輸出\輸入操作

2.get方法參數是帶在鏈接上的,所以沒有單獨賦值操作。直接在啟動鏈接通道后得到輸入流就可以得到返回值

3.post方法參數不帶在鏈接上,須要單獨賦值(賦值是使用輸出流來進行的)。須要將輸出打開(conn.setDoOutput(true);)由于URLConnection默認輸出是false。而input是默認打開的。故不用反復設置。

4.讀取返回值方式一樣。


在研究過程中,對于URLConnection如何得到的InputStream比較好奇。查看源代碼為:

public InputStream getInputStream() throws IOException {throw new UnknownServiceException("protocol doesn't support input");}
所以非常迷惑,是jdk1.7 。等下來研究出來再補上來。

共勉!

-----------------------------------------------------------------

緊跟上面。對于jdk如何實現的getInputStream和getOutputStream以及其它一些方法,經過研究。最終找到了。接下來釋疑:

須要注意到:

URL url = new URL(ACCESS_TOKEN_WEIXIN);conn = (HttpURLConnection)url.openConnection();


這里得到HttpUrlConnection的時候是使用了強轉得到的,故跟蹤到URL類的openConnection方法內->

public URLConnection openConnection() throws java.io.IOException {return handler.openConnection(this);}


這里的handler定義在URL類的上方->

transient URLStreamHandler handler;
然后去尋找handler的賦值方法getURLStreamHandler。發現例如以下代碼->

if (handler == null) {String packagePrefixList = null;packagePrefixList= java.security.AccessController.doPrivileged(new sun.security.action.GetPropertyAction(protocolPathProp,""));if (packagePrefixList != "") {packagePrefixList += "|";}// REMIND: decide whether to allow the "null" class prefix// or not.packagePrefixList += JDK_PACKAGE_PREFIX;StringTokenizer packagePrefixIter =new StringTokenizer(packagePrefixList, "|");while (handler == null &&packagePrefixIter.hasMoreTokens()) {String packagePrefix =packagePrefixIter.nextToken().trim();// do not try to instantiate the JDK gopher handler// unless the system property had been explicitly setif (protocol.equalsIgnoreCase(GOPHER) &&packagePrefix.equals(JDK_PACKAGE_PREFIX) &&!enableGopher) {continue;}try {String clsName = packagePrefix + "." + protocol +".Handler";Class cls = null;try {cls = Class.forName(clsName);
當中JDK_PACKAGE_PREFIX在類中定義的是:

private static final String JDK_PACKAGE_PREFIX = "sun.net.www.protocol";再結合以下的
String clsName = packagePrefix + "." + protocol +".Handler";基本能夠定位到handler類的實現類在sun.net.www.protocol.http.Handler。

然后百度搜索之后找到源代碼(jdk下沒有sun包的源代碼)->

sun.net.www.protocol.http包的視圖??Handler.java的源代碼?->

protected java.net.URLConnection openConnection(URL u)throws IOException {return openConnection(u, (Proxy)null);}protected java.net.URLConnection openConnection(URL u, Proxy p)throws IOException {return new HttpURLConnection(u, p, this);}
能夠看到返回值是HttpURLConnection,可是發現該類中并沒有引入java.net.HttpURLConnection類,故推測在Handler的同包下有一個同名類,果然發現該類,源代碼?->

public class HttpURLConnection extends java.net.HttpURLConnection
這是關建行,該類繼承了java.net.HttpURLConnection類。所以返回該類能夠由java.net.HttpURLConnection類的父類URLConnection接到,然后強轉成java.net.HttpURLConnection類。設計十分巧妙->

@Overridepublic synchronized OutputStream getOutputStream() throws IOException {try {if (!doOutput) {throw new ProtocolException("cannot write to a URLConnection"+ " if doOutput=false - call setDoOutput(true)");}if (method.equals("GET")) {method = "POST"; // Backward compatibility}if (!"POST".equals(method) && !"PUT".equals(method) &&"http".equals(url.getProtocol())) {throw new ProtocolException("HTTP method " + method +" doesn't support output");}// if there's already an input stream open, throw an exceptionif (inputStream != null) {throw new ProtocolException("Cannot write output after reading input.");}if (!checkReuseConnection())connect();......

這就是getOutputStream的實現地方了,正好doOutput屬性的設置也在這里起到了作用。

艾瑪,最終找到實現的地方了。其它方法原理一致了。

略微整理下:整個的類流轉過程就是:sun.net.www.protocol.http.HttpURLConnection轉化成java.net.URLConnection,然后強轉成java.net.HttpURLConnection。

暈乎~





轉載于:https://www.cnblogs.com/mfrbuaa/p/5196515.html

總結

以上是生活随笔為你收集整理的HttpUrlConnection get和post简单实现(疑惑解决)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。