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 ",如下:
代码内容如下:
刚刚我们说过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代码如下:
右击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:
其中使用到的工具类StreamTools如下:
ByteArrayOutputStream类:是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区
ByteArrayInputStream:的实例向数组中写入或读出byte型数据。
具体用法:
ByteArrayOutputStream: 可以捕获内存缓冲区的数据,转换成字节数组
ByteArrayInputStream: 可以将字节数组转化为输入流
(2)布局文件activity_main.xml:
布局效果图如下:
(3) 布署程序到模拟器上,我们进行演示:
当我们输入QQ账号:10000,QQ密码:123123,效果如下:
点击登录,出现”Login Failed",如下:
与此同时,我们的Tomcat服务器端也接收到了账号和密码:
(4)当我们输入正确的QQ账号和密码时候:
同时我们看到了Tomcat服务器上面,也收到QQ账号和QQ密码的信息,如下:
(5)小结:
我们点击"登录",程序中提取到QQ账号 和 QQ密码,组拼成url网络访问路径,访问Tomcat服务器;
Tomcat服务器得到账号和密码,会在LoginServlet程序中进行比对,如果匹配成功就返回"Login Success",匹配失败就是返回"Login Failed";
返回的信息数据,手机端程序获取之后,以土司的形式打印出来,提示用户登录的情况。
组拼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";
返回的信息数据,手机端程序获取之后,以土司的形式打印出来,提示用户登录的情况。
相关文章推荐
- Android学习系列之(六)Fragment初涉
- Android:使用fragment(碎片)—让你的应用更灵活(一)简单运用
- Android Universal Image Loader 源码分析
- android图片压缩终极解决方案
- Android中JNI的使用方法
- android6.0进入Material Design时代
- android-百度地图
- Android延时执行调用的几种方法
- Android的Tween动画与控制动画的Interpolator
- android 的service
- android-Fragment和Activity通信:将Fragment中的数据传入Activity
- Android Api Demos登顶之路(五十七)Service Remote Service Binding options
- Android 实现适配器中的子控件与Activity通信
- Android ListView —— Adapter, BaseAdapter, RecycleBin
- android fragment 详解(二)
- Android应用程序的权限列表
- Android View.OnTouchListener 的子类,AutoScrollHelper,ZoomButtonsController,ListViewAutoScrollHelper
- 关于android studio的代码显示行数的问题
- android ListView 防止图片上拉跳动
- [转]Android Parcelable和Serializable的区别