您的位置:首页 > 移动开发 > Android开发

Android(java)学习笔记209:采用get请求提交数据到服务器(qq登录案例)

2015-09-05 11:54 961 查看
1.GET请求:

组拼url的路径,把提交的数据拼装url的后面,提交给服务器。

缺点:(1)安全性(Android下提交数据组拼隐藏在代码中,不存在安全问题) (2)长度有限不能超过4K(http协议限制),IE浏览器限制至1K

优点:代码方便编写

2.我们首先在电脑模拟下GET请求访问服务器的场景

(1)使用Eclipse 新建一个 " 动态web项目 ",如下:





(2)然后编写一个servlet程序(运行在服务端),命名为" LoginServlet ",如下:





代码内容如下:

 package com.himi.web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String qq = request.getParameter("qq");
String password = request.getParameter("password");
System.out.println("qq:"+qq);
System.out.println("password:"+password);

//模拟服务器操作,查询数据库,看qq和密码是否正确. response.getOutputStream()获得一个输出流,向浏览器写入数据(提示数据).这里是输出Output,服务器输出到浏览器
if("10086".equals(qq) && "123456".equals(password)) {
response.getOutputStream().write("Login Success".getBytes());
}else {
response.getOutputStream().write("Login Failed".getBytes());
}

}

}


刚刚我们说过GET请求方法,把提交的数据组拼到url路径上提交到服务器上,所以这里request.getParameter();

(3)接下来编写一个jsp动态页面(区别于html静态页面),首先我们说一下jsp和html区别,如下:

[b]jsp和html区别:[/b]

[b] •HTML页面是静态页面,也就是事先由用户写好放在服务器上,由web服务器向客户端发送;JSP页面是动态[b][b]页面[/b],有JSP容器执行该页面的Java代码部分然后实时生成的页面.[/b][/b]

•定义上HTML页面是静态页面可以直接运行,JSP页面是动态页它运行时需要转换成servlet。

[b] •HTML能直接打开,jsp只能发布到Tomact等服务器上才能打开[/b]

•他们的表头不同,这个是JSP的头“ <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>”在表头中有编码格式和倒入包等。

•很好区分的在jsp中用<%%>就可以写Java代码了,而html没有<%%>。

编写一个login.jsp代码,在WebContent文件夹下:





login.jsp代码如下:

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>???????</title>
</head>
<body>

<form action="LoginServlet" method="get">
请输入QQ账号: <input type="text" name="qq"> <br/>
请输入QQ密码: <input type="password" name="password"> <br/>
<input type="submit" value="登录">
</form>
</body>
</html>


右击login.jsp文件," 运行方式 "--> " 在服务器上运行 ";运行的结果如下:





(4)打开360浏览器抓包分析http通信的详细过程:

• 打开360浏览器,地址栏输入:http://localhost:8080/web/login.jsp,结果如下:



•随便输入一个QQ账号和QQ密码,输入QQ账号:10000,输入QQ密码:123123,[b]如下:[/b]



观察下面,我们可以观察到我们输入的QQ账号和QQ密码已经传输到Tomcat服务器上:



详细的抓取数据包如下:





上面提到的Response的数据长度是12(字符数),如下[b]Response数据内容:[/b]





• 输入正确的QQ账号和QQ密码,如下:





由下面我们知道了我们输入的QQ账号和QQ密码已经传输到Tomcat服务器上面:





同样抓取的数据包为:





上面提到的Response的数据长度是13(字符数),如下[b]Response数据内容:[/b]



(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";

•返回的数据包被电脑浏览器获取,然后提取出返回数据,显示在浏览上,这样浏览器上就出现了[b]"Login Success"或[b]"Login Failed";[/b][/b]

3.Android下模拟出手机GET请求访问远端服务器场景:

(1)新建一个Android工程,命名为”qq登录",下面首先是MainActivity.java:

 package com.itheima.qqlogin;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
private static final String Tag = "MainActivity";
private EditText et_qq;
private EditText et_pwd;
private CheckBox cb_remember;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//查询关心的控件
et_qq = (EditText) findViewById(R.id.et_qq);
et_pwd = (EditText) findViewById(R.id.et_pwd);
cb_remember = (CheckBox) findViewById(R.id.cb_remember);
Log.i(Tag,"oncreate 被调用");
//完成数据的回显。
readSavedData();
}
//读取保存的数据
private void readSavedData() {
// getFilesDir() == /data/data/包名/files/  获取文件的路径 一般系统是不会清理的。 用户手工清理,系统会有提示。
// getCacheDir()==  /data/data/包名/cache/ 缓存文件的路径 当系统内存严重不足的时候 系统会自动的清除缓存 用户手工清理系统没有提示
File file = new File(getFilesDir(),"info.txt");
if(file.exists()&&file.length()>0){
try {
//FileInputStream fis = new FileInputStream(file);
FileInputStream fis =this.openFileInput("info.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
//214342###abcdef
String info = br.readLine();
String qq = info.split("###")[0];
String pwd = info.split("###")[1];
et_qq.setText(qq);
et_pwd.setText(pwd);
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 登陆按钮的点击事件,在点击事件里面获取数据
* @param view
*/
public void login(View view){
final String qq = et_qq.getText().toString().trim();
final String pwd = et_pwd.getText().toString().trim();
if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(pwd)){
Toast.makeText(this, "qq号码或者密码不能为空", 0).show();
return;
}
//判断用户是否勾选记住密码。
if(cb_remember.isChecked()){
//保存密码
Log.i(Tag,"保存密码");
try {
//                File file = new File(getFilesDir(),"info.txt");
//                FileOutputStream fos = new FileOutputStream(file);
FileOutputStream fos = this.openFileOutput("info.txt", 0);
//214342###abcdef
fos.write((qq+"###"+pwd).getBytes());
fos.close();
Toast.makeText(this, "保存成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "保存失败", 0).show();
}
}else{
//无需保存密码
Log.i(Tag,"无需保存密码");
}

//登录的操作,网络的请求
new Thread() {
public void run() {
//String path = "http://localhost:8080/web/LoginServlet";这里不能写成localhost
try {
String path = getString(R.string.serverip);
URL url = new URL(path+"?qq="+qq+"&password="+pwd);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if(code == 200) {
InputStream is = conn.getInputStream();
String result = StreamTools.readStream(is);
showToastInAnyThread(result);
}else {
showToastInAnyThread("请求失败");
}
} catch (Exception e) {
e.printStackTrace();
showToastInAnyThread("请求失败");
}
};
}.start();

}

/**
* 显示土司 在主线程更新UI
* @param text
*/
public void showToastInAnyThread(final String text) {
runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(MainActivity.this, text, 0).show();

}
});
}
}


其中使用到的工具类StreamTools如下:

 package com.itheima.qqlogin;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

/**
* 流的工具类
* @author Administrator
*
*/
public class StreamTools {
/**
* 把输入流的内容转换成字符串
* @param is
* @return null解析失败, string读取成功
*/
public static String readStream(InputStream is) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
is.close();
String result = baos.toString();
baos.close();
return result;

}
}


ByteArrayOutputStream类:是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区

ByteArrayInputStream:的实例向数组中写入或读出byte型数据。

具体用法:

ByteArrayOutputStream: 可以捕获内存缓冲区的数据,转换成字节数组

ByteArrayInputStream: 可以将字节数组转化为输入流

(2)布局文件activity_main.xml:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:orientation="vertical" >

<ImageView
android:layout_width="200dip"
android:layout_height="200dip"
android:src="@drawable/ic_launcher" />

<EditText
android:id="@+id/et_qq"
android:inputType="text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入qq号码" />

<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
android:inputType="textPassword" />

<CheckBox
android:id="@+id/cb_remember"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="记住密码"
/>

<Button
android:onClick="login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登陆"

/>
</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";

返回的信息数据,手机端程序获取之后,以土司的形式打印出来,提示用户登录的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: