網絡相關係列之三:通過GET和POST方法發送數據

寫在最前面:年少的安逸舒適在隨着年齡的到來和現實生活的壓迫總有一天會全數歸還(其實就是《無間道》中那句:“出來混,遲早要還的!“)

so fighting!

一、GET和POST的對比:

在漫長的時間當中,其他的方法逐漸的退出了歷史舞臺,最常用的只剩下GET和POST方法。而之前已經講過了通過GET方法獲取數據,今天來學習一下如何分別通過GET和POST獲取數據。

舉個例子:get類似於明信片,只有請求頭,沒有請求體。而post類似於一封信,信封上的內容爲請求頭;信裏面的內容爲請求體(請求頭和請求體是分開的)。

含義如下:

  • GET:通過請求URI得到資源。一般用於獲取/查詢資源信息。
  • POST:用於向服務器提交新的內容。一般用於更新資源信息。

主要區別如下:

  • GET方法主要用於從服務器取回數據,POST用於向服務器提交數據
  • get類似於明信片,只有請求頭,沒有請求體;post類似於一封信,信封上的內容爲請求頭;信裏面的內容爲請求體
  • 使用GET方法向服務器提交的數據量較小,通常不超過1K,使用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請求的實體內容中進行傳輸,相對慢,安全性較高 ,請求數據的大小沒有限制

二、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:

Tomcat 服務器是一個免費的開放源代碼的Web 應用服務器,屬於輕量級應用服務器,在中小型系統和併發訪問用戶不是很多的場合下被普遍使用,是開發和調試JSP 程序的首選。對於一個初學者來說,可以這樣認爲,當在一臺機器上配置好Apache 服務器,可利用它響應HTML(標準通用標記語言下的一個應用)頁面的訪問請求。實際上Tomcat 部分是Apache 服務器的擴展,但它是獨立運行的,所以當你運行tomcat 時,它實際上作爲一個與Apache 獨立的進程單獨運行的。

有了這個服務器,就相當於在本地的計算機有了一個網站,然後我們可以通過瀏覽器來訪問這個網站。

軟件下載鏈接:http://tomcat.apache.org/

下面看一下ubuntu12.04(我的環境)下的配置安裝過程:

1、從官方網站上下載tomcat軟件包。

 http://tomcat.apache.org/

  點擊左側的download的一個版本,我選擇的是 tomcat8.0,你可以根據自己的實際情況進行選擇安裝,點擊超連接,選擇 Binary Distributions 下的tar.gz (pgp, md5) 壓縮包,進行下載

2、下載到本地後,進行解壓

tar zxvf apache-tomcat-8.0.33 

3、進行tomcat環境的配置(前提需要安裝jdk)

在/etc/profile文件末尾添加一句並保存:

    export TOMCAT_HOME=/你的解壓目錄/apach-tomcat-8.0.33

然後source /etc/profile

4、啓動tomcat服務器

進入剛纔的tomcat解壓後的目錄中的bin目錄下,執行start.sh腳本,服務器就會啓動

5、在瀏覽器中輸入http://localhost:8080/就可以看到tomcat的log了:


我們現在在瀏覽器上測試一下它吧:

首先在opt/apache-tomcat-8.0.33/webapps/ROOT目錄中新建一個test.jsp文件:

<%
String name = request.getParameter("name");
String pwd = request.getParameter("password");
out.print("name:" + name + ",password:" + pwd); //在瀏覽器上顯示輸入地址中的用戶名與密碼
%>

現在我們隨便起一個用戶名和密碼的賬號,比如用戶名andy,密碼爲koozxcv,然後在瀏覽器中輸入如下內容:

http://localhost:8080/test.jsp?name=andy&password=koozxcv

輸入這個鏈接之後,回車,出現如下界面:


上圖中表示,我們向服務器發送這樣一個請求,鏈接中,問號前面的內容代表請求的路徑,問號後面是我們要傳送的參數(鍵是固定不變的,值是用戶自己填寫的),然後服務器返還給我們這樣的數據。

四、使用GET方法向服務器發送數據:

我們在博客“Android系列之網絡(一)”中其實就已經通過GET方法向服務器獲取數據了,只不過那篇文章中是訪問百度首頁,然後獲取百度首頁的數據。現在我們要通過同樣的GET方法,只不過是換成了獲取本地服務器搭建的網站數據。

只需要稍微修改一下那篇文章中的代碼(代碼結構一樣,只是換了另外一個鏈接)。完整版代碼如下:

<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的代碼如下:

package com.example.m04_http02;

 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.NameValuePair;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.message.BasicNameValuePair;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.EditText;
 
 public class MainActivity extends Activity {
 
     private EditText nameText;
     private EditText pwdText;
     private Button button;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         nameText = (EditText) findViewById(R.id.nameText);
         pwdText = (EditText) findViewById(R.id.pwdText);
         button = (Button) findViewById(R.id.button1);
 
         button.setOnClickListener(new OnClickListener() {
 
             @Override
             public void onClick(View v) {
                 // TODO Auto-generated method stub
                 // 用戶輸入用戶名密碼, 然後通過Get方法發送給本地服務器
                 String name = nameText.getText().toString();
                 String pwd = pwdText.getText().toString();
 
                 // 運行線程,使用GET方法向本地服務器發送數據
                 GetThread getThread = new GetThread(name, pwd);
                 getThread.start();
             }
         });
     }
     
     //子線程:通過GET方法向服務器發送用戶名、密碼的信息
     class GetThread extends Thread {
 
         String name;
         String pwd; 
         public GetThread(String name, String pwd) {
             this.name = name;
             this.pwd = pwd;
         }
 
         @Override
         public void run() {
             //用HttpClient發送請求,分爲五步
             //第一步:創建HttpClient對象
             HttpClient httpClient = new DefaultHttpClient();
             String url = "http://localhost:8080/test.jsp?name=" + name+ "&password=" + pwd;
             //第二步:創建代表請求的對象,參數是訪問的服務器地址
             HttpGet httpGet = new HttpGet(url);
             try {
                 //第三步:執行請求,獲取服務器發還的相應對象
                 HttpResponse response = httpClient.execute(httpGet);
                 //第四步:檢查相應的狀態是否正常:檢查狀態碼的值是200表示正常
                 if (response.getStatusLine().getStatusCode() == 200) {
                     //第五步:從相應對象當中取出數據,放到entity當中
                     HttpEntity entity = response.getEntity();
                     BufferedReader reader = new BufferedReader(
                             new InputStreamReader(entity.getContent()));
                     String result = reader.readLine();
                     Log.d("HTTP", "GET:" + result);
                 }
             } catch (Exception e) {
                 e.printStackTrace();
             }
 
         }
     }
 } 
運行程序後,輸入用戶名密碼,可以看到在後臺打印出了我們所輸入的用戶名和密碼:


五、使用POST方法向服務器發送數據:

上一段中,我們是通過GET方法向服務器發送數據,現在通過POST方法向服務器發送數據。佈局文件的代碼不變,就不寫了。MainActivity.java的代碼如下:

<span style="font-family:Verdana, Arial, Helvetica, sans-serif;">  package com.example.m04_http02; 
  import java.io.BufferedReader;
  import java.io.InputStreamReader;
  import java.util.ArrayList;
  
  import org.apache.http.HttpEntity;
  import org.apache.http.HttpResponse;
  import org.apache.http.NameValuePair;
  import org.apache.http.client.HttpClient;
  import org.apache.http.client.entity.UrlEncodedFormEntity;
  import org.apache.http.client.methods.HttpGet;
  import org.apache.http.client.methods.HttpPost;
  import org.apache.http.impl.client.DefaultHttpClient;
  import org.apache.http.message.BasicNameValuePair;
  
  import android.app.Activity;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.EditText;
  
  public class MainActivity extends Activity {
  
      private EditText nameText;
      private EditText pwdText;
      private Button button;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          nameText = (EditText) findViewById(R.id.nameText);
          pwdText = (EditText) findViewById(R.id.pwdText);
          button = (Button) findViewById(R.id.button1);
  
          button.setOnClickListener(new OnClickListener() {
  
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
                  // 用戶輸入用戶名密碼, 然後通過Get方法發送給本地服務器
                  String name = nameText.getText().toString();
                  String pwd = pwdText.getText().toString();
  
                  // 使用GET方法向本地服務器發送數據
                  //GetThread getThread = new GetThread(name, pwd);
                  //getThread.start();                
                  
                  //使用POST方法向服務器發送數據
                  PostThread postThread = new PostThread(name, pwd);
                  postThread.start();
              }
          });
      }
  
  
      //子線程:通過GET方法向服務器發送用戶名、密碼的信息
      class GetThread extends Thread {
  
          String name;
          String pwd;
  
          public GetThread(String name, String pwd) {
              this.name = name;
              this.pwd = pwd;
          }
  
          @Override
          public void run() {
              //用HttpClient發送請求,分爲五步
              //第一步:創建HttpClient對象
              HttpClient httpClient = new DefaultHttpClient();
              String url = "http://192.168.191.4:8080/test.jsp?name=" + name+ "&password=" + pwd;
              //第二步:創建代表請求的對象,參數是訪問的服務器地址
              HttpGet httpGet = new HttpGet(url);
              try {
                  //第三步:執行請求,獲取服務器發還的相應對象
                  HttpResponse response = httpClient.execute(httpGet);
                  //第四步:檢查相應的狀態是否正常:檢查狀態碼的值是200表示正常
                  if (response.getStatusLine().getStatusCode() == 200) {
                      //第五步:從相應對象當中取出數據,放到entity當中
                      HttpEntity entity = response.getEntity();
                      BufferedReader reader = new BufferedReader(
                              new InputStreamReader(entity.getContent()));
                      String result = reader.readLine();
                      Log.d("HTTP", "GET:" + result);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
  
          }
      }    
      
      //子線程:使用POST方法向服務器發送用戶名、密碼等數據
     class PostThread extends Thread {
 
         String name;
         String pwd;
 
         public PostThread(String name, String pwd) {
             this.name = name;
             this.pwd = pwd;
         }
          @Override
         public void run() {
             HttpClient httpClient = new DefaultHttpClient();
             String url = "http://192.168.1.112:8080/test.jsp";
             //第二步:生成使用POST方法的請求對象
             HttpPost httpPost = new HttpPost(url);
             //NameValuePair對象代表了一個需要發往服務器的鍵值對
             NameValuePair pair1 = new BasicNameValuePair("name", name);
             NameValuePair pair2 = new BasicNameValuePair("password", pwd);
             //將準備好的鍵值對對象放置在一個List當中
             ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
             pairs.add(pair1);
             pairs.add(pair2);
             try {
                 //創建代表請求體的對象(注意,是請求體)
                 HttpEntity requestEntity = new UrlEncodedFormEntity(pairs);
                 //將請求體放置在請求對象當中
                 httpPost.setEntity(requestEntity);
                 //執行請求對象
                 try {
                     //第三步:執行請求對象,獲取服務器發還的相應對象</span>
                     HttpResponse response = httpClient.execute(httpPost);
                     //第四步:檢查相應的狀態是否正常:檢查狀態碼的值是200表示正常
                     if (response.getStatusLine().getStatusCode() == 200) {
                         //第五步:從相應對象當中取出數據,放到entity當中
                         HttpEntity entity = response.getEntity();
                         BufferedReader reader = new BufferedReader(
                                 new InputStreamReader(entity.getContent()));
                         String result = reader.readLine();
                         Log.d("HTTP", "POST:" + result);
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     }
     
     
 }

上方代碼中,我們新開一個子線程,使用POST方法向服務器發送用戶名、密碼等數據。我們之前已經知道,使用GET方法發送HTTP請求有五大步驟,而如今換成POST方法時,需要在第二步和第三步之間加入一些步驟多的步驟其實是往請求對象中加入請求體。現在來詳細解釋一下這部分代碼:

我們通過NameValuePair集合來存放待提交的參數,並將這個參數集合傳入到一個UrlEncodedFormEntity當中(這個類的對象就代表了一個請求體,即鍵值對),然後將請求體放置在請求對象httpPost當中。

程序運行後,輸入用戶名和密碼,點擊按鈕,在後臺打印出了之前輸入的用戶名密碼:


現在我們總結一下POST提交數據的步驟:

  • 1. 構造請求對象;
  • 2. 將需要傳遞給服務器端的數據放置在鍵值對對象當中;
  • 3. 將準備好的鍵值對放置在List當中;
  • 4. 生成代表請求體的對象;
  • 5. 將存有請求鍵值對的List對象放置在請求題對象當中;
  • 6. 將請求體對象放置到請求對象當中;
  • 7. 發送請求對象
  • 後面的步驟(即處理請求對象)和GET方法是一致的。

上面兩段的例子,都是通過GET和POST往服務器發送數據(在此,二者的作用是等價的)。需要注意的是,一般來講,GET是從服務器取數據,但在此例子中GET卻是往服務器發數據。如果是上傳文件,就必須用POST。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章