1. 程式人生 > >Android系列之網路(三)----使用HttpClient傳送HTTP請求(分別通過GET和POST方法傳送資料)

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