【正文】
在前兩篇文章中,我們學習到了和HTTP相關的基礎知識。文章鏈接如下:
Android系列之網絡(一)----使用HttpClient發送HTTP請求(通過get方法獲取數據)
Android系列之網絡(二)----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軟件在本地搭建服務器:
有了這個服務器,就相當於在本地的計算機有了一個網站,然後我們可以通過瀏覽器來訪問這個網站。
tomcat軟甲是apache旗下的一個開源項目。軟件下載鏈接:http://tomcat.apache.org/
下載之後,將壓縮包解壓:
注意目錄名不能有中文和空格。
軟件運行之前要保證環境變量已經配置:
上圖中,變量名爲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