Android系列之網路(三)----使用HttpClient傳送HTTP請求(分別通過GET和POST方法傳送資料)
【正文】
在前兩篇文章中,我們學習到了和HTTP相關的基礎知識。文章連結如下:
一、GET和POST的對比:
在漫長的時間當中,其他的方法逐漸的退出了歷史舞臺,最常用的只剩下GET和POST方法。而之前已經講過了通過GET方法獲取資料,今天來學習一下如何分別通過GET和POST獲取資料。
舉個例子:get類似於明信片,只有請求頭,沒有請求體。而post類似於一封信,信封上的內容為請求頭;信裡面的內容為請求體(請求頭和請求體是分開的)。
含義如下:
- GET:通過請求URI得到資源。一般用於獲取/查詢資源資訊。
- POST:用於向伺服器提交新的內容。一般用於更新資源資訊。
主要區別如下:
- GET方法主要用於從伺服器取回資料,POST用於向伺服器提交資料
- get類似於明信片,只有請求頭,沒有請求體;post類似於一封信,信封上的內容為請求頭;信裡面的內容為請求體
- 使用GET方法啊向伺服器i教的資料量較小,通常不超過2K,使用POST向伺服器提交的資料量通常沒有限制(明信片不能多寫,而寫信可以寫好多內容咧)
- GET請求是將所要提交的資料附在URL之後,而POST請求是將提交的資料放置在請求體當中
老羅在將到get和post請求的時候, 是這樣說的:
- 1、GET是從伺服器上獲取資料,POST是向伺服器傳送資料。
- 2、在客戶端, GET方式在通過URL提交資料,資料在URL中可以看到;POST方式,資料放置在HTML HEADER內提交
- 3、對於GET方式,伺服器端用Request.QueryString獲取變數的值,對於POST方式,伺服器端用Request.Form獲取提交的資料。
- 4、GET方式提交的資料最多隻能有1024位元組,而POST則沒有此限制
- 5、安全性問題。正如在(2)中提到,使用 GET 的時候,引數會顯示在位址列上,而 POST 不會。所以,如果這些資料是中文資料而且是非敏感資料,那麼使用 GET ;如果使用者輸入的資料不是中文字元而且包含敏感資料,那麼還是使用 POST為好
囉嗦了這麼多,對這段來個總結吧。
【總結】
get/post請求的區別:
- get請求方式:顯式請求方式,請求引數會在URL上顯示,相對快,安全性較低,請求資料的大小一般不超過1kb。
- post請求方式:隱式請求方式,請求引數將會在http請求的實體內容中進行傳輸,相對慢,安全性較高 ,請求資料的大小沒有限制
注:GET請求方式和POST請求區別在於請求引數在傳遞的過程中方式不同。
二、URL的定義和組成:
URL:Uniform Resource Locator 統一資源定位符
URL的組成部分:以http://www.mbalib.com/china/index.htm為例
- http://:代表超文字傳輸協議
- www:代表一個全球資訊網伺服器
- mbalib.com/:伺服器的域名,或伺服器名稱
- China/:子目錄,類似於我們的資料夾
- Index.htm:是資料夾中的一個檔案
- /china/index.htm統稱為URL路徑
三、使用tomcat軟體在本地搭建伺服器:
有了這個伺服器,就相當於在本地的計算機有了一個網站,然後我們可以通過瀏覽器來訪問這個網站。
下載之後,將壓縮包解壓:
注意目錄名不能有中文和空格。
軟體執行之前要保證環境變數已經配置:
上圖中,變數名為JAVA_HOME,變數值為:JDK安裝的絕對路徑。
回到tomcat的bin目錄中, 雙擊startup.bat:
之後彈出如下介面:
這個時候,本地的伺服器就已經搭建起來了。
首先檢視自己電腦的ip地址,我的計算機的ip地址為:192.168.1.112。
在瀏覽器中輸入http://192.168.1.112:8080/。如果彈出如下介面,表示tomcat安裝成功並且啟動起來了:
上方圖片中,顯示我的Tomcat的版本為:8.0.14。它的版本號是跟著JDK的版本走的,所以,建議JDK的版本為1.8。
我們現在在瀏覽器上測試一下它吧:
首先在D:\apache-tomcat-8.0.14\webapps\ROOT目錄中新建一個jsp檔案:
jsp檔案中填入如下內容:
<% String name = request.getParameter("name"); String pwd = request.getParameter("password"); out.print("name:" + name + ",password:" + pwd); //在瀏覽器上顯示輸入地址中的使用者名稱與密碼 %>
現在我們隨便起一個使用者名稱和密碼的賬號,比如使用者名稱smyhvae,密碼為smyh,然後在瀏覽器中輸入如下內容:
http://192.168.1.112:8080/test.jsp?name=smyhvae&password=smyh
輸入這個連結之後,回車,出現如下介面:
上圖中表示,我們向伺服器傳送這樣一個請求,連結中,問號前面的內容代表請求的路徑,問號後面是我們要傳送的引數(鍵是固定不變的,值是使用者自己填寫的),然後伺服器返還給我們這樣的資料。
四、使用GET方法向伺服器傳送資料:
我們在部落格“Android系列之網路(一)”中其實就已經通過GET方法向伺服器獲取資料了,只不過那篇文章中是訪問百度首頁,然後獲取百度首頁的資料。現在我們要通過同樣的GET方法,只不過是換成了獲取本地伺服器搭建的網站資料。
只需要稍微修改一下那篇文章中的程式碼(程式碼結構一樣,只是換了另外一個連結)。完整版程式碼如下:
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <EditText android:id="@+id/nameText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="username" /> <EditText android:id="@+id/pwdText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="password" /> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="submit" /> </LinearLayout>
MainActivity.java的程式碼如下:
1 package com.example.m04_http02; 2 3 import java.io.BufferedReader; 4 import java.io.InputStreamReader; 5 import java.util.ArrayList; 6 import org.apache.http.HttpEntity; 7 import org.apache.http.HttpResponse; 8 import org.apache.http.NameValuePair; 9 import org.apache.http.client.HttpClient; 10 import org.apache.http.client.entity.UrlEncodedFormEntity; 11 import org.apache.http.client.methods.HttpGet; 12 import org.apache.http.client.methods.HttpPost; 13 import org.apache.http.impl.client.DefaultHttpClient; 14 import org.apache.http.message.BasicNameValuePair; 15 16 import android.app.Activity; 17 import android.os.Bundle; 18 import android.util.Log; 19 import android.view.View; 20 import android.view.View.OnClickListener; 21 import android.widget.Button; 22 import android.widget.EditText; 23 24 public class MainActivity extends Activity { 25 26 private EditText nameText; 27 private EditText pwdText; 28 private Button button; 29 30 @Override 31 protected void onCreate(Bundle savedInstanceState) { 32 super.onCreate(savedInstanceState); 33 setContentView(R.layout.activity_main); 34 nameText = (EditText) findViewById(R.id.nameText); 35 pwdText = (EditText) findViewById(R.id.pwdText); 36 button = (Button) findViewById(R.id.button1); 37 38 button.setOnClickListener(new OnClickListener() { 39 40 @Override 41 public void onClick(View v) { 42 // TODO Auto-generated method stub 43 // 使用者輸入使用者名稱密碼, 然後通過Get方法傳送給本地伺服器 44 String name = nameText.getText().toString(); 45 String pwd = pwdText.getText().toString(); 46 47 // 執行執行緒,使用GET方法向本地伺服器傳送資料 48 GetThread getThread = new GetThread(name, pwd); 49 getThread.start(); 50 } 51 }); 52 } 53 54 //子執行緒:通過GET方法向伺服器傳送使用者名稱、密碼的資訊 55 class GetThread extends Thread { 56 57 String name; 58 String pwd; 59 60 public GetThread(String name, String pwd) { 61 this.name = name; 62 this.pwd = pwd; 63 } 64 65 @Override 66 public void run() { 67 //用HttpClient傳送請求,分為五步 68 //第一步:建立HttpClient物件 69 HttpClient httpClient = new DefaultHttpClient(); 70 //注意,下面這一行中,我之前把連結中的"test"誤寫成了"text",導致調BUG調了半天沒弄出來,真是浪費時間啊 71 String url = "http://192.168.1.112:8080/test.jsp?name=" + name+ "&password=" + pwd; 72 //第二步:建立代表請求的物件,引數是訪問的伺服器地址 73 HttpGet httpGet = new HttpGet(url); 74 try { 75 //第三步:執行請求,獲取伺服器發還的相應物件 76 HttpResponse response = httpClient.execute(httpGet); 77 //第四步:檢查相應的狀態是否正常:檢查狀態碼的值是200表示正常 78 if (response.getStatusLine().getStatusCode() == 200) { 79 //第五步:從相應物件當中取出資料,放到entity當中 80 HttpEntity entity = response.getEntity(); 81 BufferedReader reader = new BufferedReader( 82 new InputStreamReader(entity.getContent())); 83 String result = reader.readLine(); 84 Log.d("HTTP", "GET:" + result); 85 } 86 } catch (Exception e) { 87 e.printStackTrace(); 88 } 89 90 } 91 } 92 }
上方程式碼中,第73行就是我們所放入的url連結。執行程式後,輸入使用者名稱密碼,可以看到在後臺打印出了我們所輸入的使用者名稱和密碼:
五、使用POST方法向伺服器傳送資料:
上一段中,我們是通過GET方法向伺服器傳送資料,現在通過POST方法向伺服器傳送資料。佈局檔案的程式碼不變,就不寫了。MainActivity.java的程式碼如下:
1 package com.example.m04_http02; 2 3 import java.io.BufferedReader; 4 import java.io.InputStreamReader; 5 import java.util.ArrayList; 6 7 import org.apache.http.HttpEntity; 8 import org.apache.http.HttpResponse; 9 import org.apache.http.NameValuePair; 10 import org.apache.http.client.HttpClient; 11 import org.apache.http.client.entity.UrlEncodedFormEntity; 12 import org.apache.http.client.methods.HttpGet; 13 import org.apache.http.client.methods.HttpPost; 14 import org.apache.http.impl.client.DefaultHttpClient; 15 import org.apache.http.message.BasicNameValuePair; 16 17 import android.app.Activity; 18 import android.os.Bundle; 19 import android.util.Log; 20 import android.view.View; 21 import android.view.View.OnClickListener; 22 import android.widget.Button; 23 import android.widget.EditText; 24 25 public class MainActivity extends Activity { 26 27 private EditText nameText; 28 private EditText pwdText; 29 private Button button; 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_main); 35 nameText = (EditText) findViewById(R.id.nameText); 36 pwdText = (EditText) findViewById(R.id.pwdText); 37 button = (Button) findViewById(R.id.button1); 38 39 button.setOnClickListener(new OnClickListener() { 40 41 @Override 42 public void onClick(View v) { 43 // TODO Auto-generated method stub 44 // 使用者輸入使用者名稱密碼, 然後通過Get方法傳送給本地伺服器 45 String name = nameText.getText().toString(); 46 String pwd = pwdText.getText().toString(); 47 48 // 使用GET方法向本地伺服器傳送資料 49 //GetThread getThread = new GetThread(name, pwd); 50 //getThread.start(); 51 52 //使用POST方法向伺服器傳送資料 53 PostThread postThread = new PostThread(name, pwd); 54 postThread.start(); 55 } 56 }); 57 } 58 59 60 //子執行緒:通過GET方法向伺服器傳送使用者名稱、密碼的資訊 61 class GetThread extends Thread { 62 63 String name; 64 String pwd; 65 66 public GetThread(String name, String pwd) { 67 this.name = name; 68 this.pwd = pwd; 69 } 70 71 @Override 72 public void run() { 73 //用HttpClient傳送請求,分為五步 74 //第一步:建立HttpClient物件 75 HttpClient httpClient = new DefaultHttpClient(); 76 //注意,下面這一行中,我之前把連結中的"test"誤寫成了"text",導致調BUG調了半天沒弄出來,真是浪費時間啊 77 String url = "http://192.168.1.112:8080/test.jsp?name=" + name+ "&password=" + pwd; 78 //第二步:建立代表請求的物件,引數是訪問的伺服器地址 79 HttpGet httpGet = new HttpGet(url); 80 try { 81 //第三步:執行請求,獲取伺服器發還的相應物件 82 HttpResponse response = httpClient.execute(httpGet); 83 //第四步:檢查相應的狀態是否正常:檢查狀態碼的值是200表示正常 84 if (response.getStatusLine().getStatusCode() == 200) { 85 //第五步:從相應物件當中取出資料,放到entity當中 86 HttpEntity entity = response.getEntity(); 87 BufferedReader reader = new BufferedReader( 88 new InputStreamReader(entity.getContent())); 89 String result = reader.readLine(); 90 Log.d("HTTP", "GET:" + result); 91 } 92 } catch (Exception e) { 93 e.printStackTrace(); 94 } 95 96 } 97 } 98 99 //子執行緒:使用POST方法向伺服器傳送使用者名稱、密碼等資料 100 class PostThread extends Thread { 101 102 String name; 103 String pwd; 104 105 public PostThread(String name, String pwd) { 106 this.name = name; 107 this.pwd = pwd; 108 } 109 110 @Override 111 public void run() { 112 HttpClient httpClient = new DefaultHttpClient(); 113 String url = "http://192.168.1.112:8080/test.jsp"; 114 //第二步:生成使用POST方法的請求物件 115 HttpPost httpPost = new HttpPost(url); 116 //NameValuePair物件代表了一個需要發往伺服器的鍵值對 117 NameValuePair pair1 = new BasicNameValuePair("name", name); 118 NameValuePair pair2 = new BasicNameValuePair("password", pwd); 119 //將準備好的鍵值對物件放置在一個List當中 120 ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>(); 121 pairs.add(pair1); 122 pairs.add(pair2); 123 try { 124 //建立代表請求體的物件(注意,是請求體) 125 HttpEntity requestEntity = new UrlEncodedFormEntity(pairs); 126 //將請求體放置在請求物件當中 127 httpPost.setEntity(requestEntity); 128 //執行請求物件 129 try { 130 //第三步:執行請求物件,獲取伺服器發還的相應物件 131 HttpResponse response = httpClient.execute(httpPost); 132 //第四步:檢查相應的狀態是否正常:檢查狀態碼的值是200表示正常 133 if (response.getStatusLine().getStatusCode() == 200) { 134 //第五步:從相應物件當中取出資料,放到entity當中 135 HttpEntity entity = response.getEntity(); 136 BufferedReader reader = new BufferedReader( 137 new InputStreamReader(entity.getContent())); 138 String result = reader.readLine(); 139 Log.d("HTTP", "POST:" + result); 140 } 141 } catch (Exception e) { 142 e.printStackTrace(); 143 } 144 } catch (Exception e) { 145 e.printStackTrace(); 146 } 147 } 148 } 149 150 151 }
上方程式碼中,我們新開一個子執行緒,使用POST方法向伺服器傳送使用者名稱、密碼等資料。我們之前已經知道,使用GET方法傳送HTTP請求有五大步驟,而如今換成POST方法時,需要在第二步和第三步之間加入一些步驟(即上方加粗部分的程式碼:116-127行),多的步驟其實是往請求物件中加入請求體。現在來詳細解釋一下這部分程式碼:
我們通過NameValuePair集合來存放待提交的引數,並將這個引數集合傳入到一個UrlEncodedFormEntity當中(這個類的物件就代表了一個請求體,即鍵值對),然後將請求體放置在請求物件httpPost當中。
程式執行後,輸入使用者名稱和密碼,點選按鈕,在後臺打印出了之前輸入的使用者名稱密碼:
現在我們總結一下POST提交資料的步驟:
- 1. 構造請求物件;
- 2. 將需要傳遞給伺服器端的資料放置在鍵值對物件當中;
- 3. 將準備好的鍵值對放置在List當中;
- 4. 生成代表請求體的物件;
- 5. 將存有請求鍵值對的List物件放置在請求題物件當中;
- 6. 將請求體物件放置到請求物件當中;
- 7. 傳送請求物件
- 後面的步驟(即處理請求物件)和GET方法是一致的。
上面兩段的例子,都是通過GET和POST往伺服器傳送資料(在此,二者的作用是等價的)。需要注意的是,一般來講,GET是從伺服器取資料,但在此例子中GET卻是往伺服器發資料。如果是上傳檔案,就必須用POST。我們將在今後的章節中講到。
【工程檔案】
連結:http://pan.baidu.com/s/1euPiQ
密碼:00y6