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";
返回的信息數據,手機端程序獲取以後,以土司的形式打印出來,提示用戶登陸的狀況。