Android(java)學習筆記152:採用get請求提交數據到服務器(qq登陸案例)

1.GET請求:html

   組拼url的路徑,把提交的數據拼裝url的後面,提交給服務器。java

缺點:(1)安全性(Android下提交數據組拼隱藏在代碼中,不存在安全問題)  (2)長度有限不能超過4K(http協議限制),IE瀏覽器限制至1Kandroid

優勢:代碼方便編寫web

2.咱們首先在電腦模擬下GET請求訪問服務器的場景數據庫

(1)使用Eclipse 新建一個 " 動態web項目 ",以下:數組

 

 

(2)而後編寫一個servlet程序(運行在服務端),命名爲" LoginServlet ",以下:瀏覽器

 

代碼內容以下:緩存

 1 package com.himi.web;  2 
 3 import java.io.IOException;  4 import javax.servlet.ServletException;  5 import javax.servlet.annotation.WebServlet;  6 import javax.servlet.http.HttpServlet;  7 import javax.servlet.http.HttpServletRequest;  8 import javax.servlet.http.HttpServletResponse;  9 
10 /**
11  * Servlet implementation class LoginServlet 12  */
13 @WebServlet("/LoginServlet") 14 public class LoginServlet extends HttpServlet { 15     private static final long serialVersionUID = 1L; 16 
17     /**
18  * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 19      */
20     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 21          String qq = request.getParameter("qq"); 22          String password = request.getParameter("password"); 23          System.out.println("qq:"+qq); 24          System.out.println("password:"+password); 25          
26//模擬服務器操做,查詢數據庫,看qq和密碼是否正確. response.getOutputStream()得到一個輸出流,向瀏覽器寫入數據(提示數據).這裏是輸出Output,服務器輸出到瀏覽器
27          if("10086".equals(qq) && "123456".equals(password)) { 28              response.getOutputStream().write("Login Success".getBytes()); 29          }else { 30              response.getOutputStream().write("Login Failed".getBytes()); 31  } 32          
33  } 34 
35 }

剛剛咱們說過GET請求方法,把提交的數據組拼到url路徑上提交到服務器上,因此這裏request.getParameter();安全

 

(3)接下來編寫一個jsp動態頁面(區別於html靜態頁面),首先咱們說一下jsp和html區別,以下:服務器

jsp和html區別:

      •HTML頁面是靜態頁面,也就是事先由用戶寫好放在服務器上,由web服務器向客戶端發送;JSP頁面是動態頁面,有JSP容器執行該頁面的Java代碼部分而後實時生成的頁面.

      •定義上HTML頁面是靜態頁面能夠直接運行,JSP頁面是動態頁它運行時須要轉換成servlet。 

      •HTML能直接打開,jsp只能發佈到Tomact等服務器上才能打開

      •他們的表頭不一樣,這個是JSP的頭「 <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>」在表頭中有編碼格式和倒入包等。

      •很好區分的在jsp中用<%%>就能夠寫Java代碼了,而html沒有<%%>。

 

編寫一個login.jsp代碼,在WebContent文件夾下

 

login.jsp代碼以下:

 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 2 <html>
 3 <head>
 4 <%@ page language="java" contentType="text/html; charset=utf-8"
 5  pageEncoding="utf-8"%>
 6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 7 <title>???????</title>
 8 </head>
 9 <body>
10     
11     <form action="LoginServlet" method="get">
12   請輸入QQ帳號: <input type="text" name="qq"> <br/>
13   請輸入QQ密碼: <input type="password" name="password"> <br/>
14     <input type="submit" value="登陸">
15     </form>
16 </body>
17 </html>

右擊login.jsp文件," 運行方式 "--> " 在服務器上運行 ";運行的結果以下:

 

(4)打開360瀏覽器抓包分析http通訊的詳細過程:

• 打開360瀏覽器,地址欄輸入:http://localhost:8080/web/login.jsp,結果以下:

•隨便輸入一個QQ帳號和QQ密碼,輸入QQ帳號10000,輸入QQ密碼123123以下:

觀察下面,咱們能夠觀察到咱們輸入的QQ帳號和QQ密碼已經傳輸到Tomcat服務器上

詳細的抓取數據包以下:

 

上面提到的Response的數據長度是12(字符數),以下Response數據內容

 

 

• 輸入正確的QQ帳號和QQ密碼,以下:

 

由下面咱們知道了咱們輸入的QQ帳號和QQ密碼已經傳輸到Tomcat服務器上面: 

一樣抓取的數據包爲:

 

上面提到的Response的數據長度是13(字符數),以下Response數據內容

(5)小結:

•首先咱們讓編寫的Servlet的程序在LoginServlet在Tomcat運行,Tomcat則處於一直監聽狀態(監聽外界Http--GET請求),當咱們在login.jsp輸入QQ帳號和QQ密碼時候,點擊"登陸"以後,瀏覽器會把QQ帳號和QQ密碼組拼到url路徑上,把這些數據提交給Tomcat服務器;

•此時處於監聽狀態的Tomcat服務器則根據接收到http的請求數據包中提取到QQ帳號和QQ密碼,比對正確的QQ帳號和QQ密碼(現實則是比對數據庫的QQ帳號和QQ密碼);

•根據QQ帳號和QQ密碼匹配情況,反饋不一樣的信息,匹配成功返回"Login Success" ,反之匹配失敗返回"Login Failed";

•返回的數據包被電腦瀏覽器獲取,而後提取出返回數據,顯示在瀏覽上,這樣瀏覽器上就出現了"Login Success"或"Login Failed";

 

3.Android下模擬出手機GET請求訪問遠端服務器場景:

(1)新建一個Android工程,命名爲」qq登陸",下面首先是MainActivity.java

 1 package com.itheima.qqlogin;  2 
 3 import java.io.BufferedReader;  4 import java.io.File;  5 import java.io.FileInputStream;  6 import java.io.FileOutputStream;  7 import java.io.InputStream;  8 import java.io.InputStreamReader;  9 import java.net.HttpURLConnection;  10 import java.net.MalformedURLException;  11 import java.net.URL;  12 
 13 import android.app.Activity;  14 import android.os.Bundle;  15 import android.text.TextUtils;  16 import android.util.Log;  17 import android.view.View;  18 import android.widget.CheckBox;  19 import android.widget.EditText;  20 import android.widget.Toast;  21 
 22 public class MainActivity extends Activity {  23     private static final String Tag = "MainActivity";  24     private EditText et_qq;  25     private EditText et_pwd;  26     private CheckBox cb_remember;  27 
 28  @Override  29     protected void onCreate(Bundle savedInstanceState) {  30         super.onCreate(savedInstanceState);  31  setContentView(R.layout.activity_main);  32         //查詢關心的控件
 33         et_qq = (EditText) findViewById(R.id.et_qq);  34         et_pwd = (EditText) findViewById(R.id.et_pwd);  35         cb_remember = (CheckBox) findViewById(R.id.cb_remember);  36         Log.i(Tag,"oncreate 被調用");  37         //完成數據的回顯。
 38  readSavedData();  39  }  40     //讀取保存的數據
 41     private void readSavedData() {  42         // getFilesDir() == /data/data/包名/files/ 獲取文件的路徑 通常系統是不會清理的。 用戶手工清理,系統會有提示。  43         // getCacheDir()== /data/data/包名/cache/ 緩存文件的路徑 當系統內存嚴重不足的時候 系統會自動的清除緩存 用戶手工清理系統沒有提示
 44         File file = new File(getFilesDir(),"info.txt");  45         if(file.exists()&&file.length()>0){  46             try {  47                 //FileInputStream fis = new FileInputStream(file);
 48                 FileInputStream fis =this.openFileInput("info.txt");  49                 BufferedReader br = new BufferedReader(new InputStreamReader(fis));  50                 //214342###abcdef
 51                 String info = br.readLine();  52                 String qq = info.split("###")[0];  53                 String pwd = info.split("###")[1];  54  et_qq.setText(qq);  55  et_pwd.setText(pwd);  56  fis.close();  57             } catch (Exception e) {  58  e.printStackTrace();  59  }  60  }  61  }  62     /**
 63  * 登錄按鈕的點擊事件,在點擊事件裏面獲取數據  64  * @param view  65      */
 66     public void login(View view){  67         final String qq = et_qq.getText().toString().trim();  68         final String pwd = et_pwd.getText().toString().trim();  69         if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(pwd)){  70             Toast.makeText(this, "qq號碼或者密碼不能爲空", 0).show();  71             return;  72  }  73         //判斷用戶是否勾選記住密碼。
 74         if(cb_remember.isChecked()){  75             //保存密碼
 76             Log.i(Tag,"保存密碼");  77             try {  78 // File file = new File(getFilesDir(),"info.txt");  79 // FileOutputStream fos = new FileOutputStream(file);
 80                 FileOutputStream fos = this.openFileOutput("info.txt", 0);  81                 //214342###abcdef
 82                 fos.write((qq+"###"+pwd).getBytes());  83  fos.close();  84                 Toast.makeText(this, "保存成功", 0).show();  85             } catch (Exception e) {  86  e.printStackTrace();  87                 Toast.makeText(this, "保存失敗", 0).show();  88  }  89         }else{  90             //無需保存密碼
 91             Log.i(Tag,"無需保存密碼");  92  }  93         
 94         //登陸的操做,網絡的請求
 95         new Thread() {  96             public void run() {  97                 //String path = "http://localhost:8080/web/LoginServlet";這裏不能寫成localhost
 98                 try {  99                     String path = getString(R.string.serverip); 100                     URL url = new URL(path+"?qq="+qq+"&password="+pwd); 101                     HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 102                     conn.setRequestMethod("GET"); 103                     int code = conn.getResponseCode(); 104                     if(code == 200) { 105                         InputStream is = conn.getInputStream(); 106                         String result = StreamTools.readStream(is); 107  showToastInAnyThread(result); 108                     }else { 109                         showToastInAnyThread("請求失敗"); 110  } 111                 } catch (Exception e) { 112  e.printStackTrace(); 113                     showToastInAnyThread("請求失敗"); 114  } 115  }; 116  }.start(); 117         
118  } 119     
120     /**
121  * 顯示土司 在主線程更新UI 122  * @param text 123      */
124     public void showToastInAnyThread(final String text) { 125         runOnUiThread(new Runnable() { 126             
127  @Override 128             public void run() { 129                 Toast.makeText(MainActivity.this, text, 0).show(); 130                 
131  } 132  }); 133  } 134 }

 

其中使用到的工具類StreamTools以下:

 1 package com.itheima.qqlogin;  2 
 3 import java.io.ByteArrayOutputStream;  4 import java.io.InputStream;  5 
 6 /**
 7  * 流的工具類  8  * @author Administrator  9  * 10  */
11 public class StreamTools { 12     /**
13  * 把輸入流的內容轉換成字符串 14  * @param is 15  * @return null解析失敗, string讀取成功 16      */
17     public static String readStream(InputStream is) throws Exception { 18             ByteArrayOutputStream baos = new ByteArrayOutputStream(); 19             byte[] buffer = new byte[1024]; 20             int len = 0; 21             while((len = is.read(buffer)) != -1) { 22                 baos.write(buffer, 0, len); 23  } 24  is.close(); 25             String result = baos.toString(); 26  baos.close(); 27             return result; 28             
29         
30  } 31 }

ByteArrayOutputStream類:是在建立它的實例時,程序內部建立一個byte型別數組的緩衝區

ByteArrayInputStream:的實例向數組中寫入或讀出byte型數據。

具體用法:

         ByteArrayOutputStream:    能夠捕獲內存緩衝區的數據,轉換成字節數組

         ByteArrayInputStream:     能夠將字節數組轉化爲輸入流

(2)佈局文件activity_main.xml

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2  android:layout_width="match_parent"
 3  android:layout_height="match_parent"
 4  android:gravity="center_horizontal"
 5  android:paddingLeft="10dp"
 6  android:paddingRight="10dp"
 7  android:orientation="vertical" >
 8 
 9     <ImageView 10         android:layout_width="200dip"
11  android:layout_height="200dip"
12  android:src="@drawable/ic_launcher" />
13 
14     <EditText 15         android:id="@+id/et_qq"
16  android:inputType="text"
17  android:layout_width="match_parent"
18  android:layout_height="wrap_content"
19  android:hint="請輸入qq號碼" />
20     
21      <EditText 22          android:id="@+id/et_pwd"
23  android:layout_width="match_parent"
24  android:layout_height="wrap_content"
25  android:hint="請輸入密碼"
26  android:inputType="textPassword" />
27      
28      <CheckBox 29          android:id="@+id/cb_remember"
30  android:layout_width="match_parent"
31  android:layout_height="wrap_content"
32  android:text="記住密碼"
33          />
34 
35      <Button 36          android:onClick="login" 
37  android:layout_width="match_parent"
38  android:layout_height="wrap_content"
39  android:text="登錄"
40          
41          />
42 </LinearLayout>

佈局效果圖以下:

 

(3) 佈署程序到模擬器上,咱們進行演示:

當咱們輸入QQ帳號:10000,QQ密碼:123123,效果以下:

 

點擊登陸,出現」Login Failed",以下:

 

與此同時,咱們的Tomcat服務器端也接收到了帳號和密碼

 

 

(4)當咱們輸入正確的QQ帳號和密碼時候:

 

同時咱們看到了Tomcat服務器上面,也收到QQ帳號和QQ密碼的信息,以下:

 

(5)小結:

咱們點擊"登陸",程序中提取到QQ帳號 和 QQ密碼,組拼成url網絡訪問路徑,訪問Tomcat服務器;

Tomcat服務器獲得帳號和密碼,會在LoginServlet程序中進行比對,若是匹配成功就返回"Login Success",匹配失敗就是返回"Login Failed";

返回的信息數據,手機端程序獲取以後,以土司的形式打印出來,提示用戶登陸的狀況。

相關文章
相關標籤/搜索