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

时间:2021-07-04 21:57:56

1.POST请求:

 数据是以流的方式写给服务器

优点:(1)比较安全 (2)长度不限制

缺点:编写代码比较麻烦

 

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

我们修改之前编写的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>
<h3>GET方式提交数据</h3>
<form action="LoginServlet" method="get">
请输入QQ账号: <input type="text" name="qq"> <br/>
请输入QQ密码: <input type="password" name="password"> <br/>
<input type="submit" value="登录">
</form> <br>
<hr>
<h3>POST方式提交数据</h3>
<form action="LoginServlet" method="post">
请输入QQ账号: <input type="text" name="qq"> <br/>
请输入QQ密码: <input type="password" name="password"> <br/>
<input type="submit" value="登录">
</form>
</body>
</html>

将修改过的jsp代码在Tomcat服务器上运行,如下:

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

我们在"POST方式提交数据"一栏,输入正确的QQ 账号和QQ密码,如下的然后提交出现如下错误:

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

这是因为在LoginServlet中只有doGet()方法,对于POST请求,服务器自然是接收不到POST请求的数据包,自然会出现上面的错误,添加doPost()方法即可:

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和密码是否正确
if("10086".equals(qq) && "123456".equals(password)) {
response.getOutputStream().write("Login Success".getBytes());
}else {
response.getOutputStream().write("Login Failed".getBytes());
} } /**
* 添加的doPost()方法,响应post数据请求
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("post过来的数据");
doGet(req, resp);
} }

这个时候我们再次刷新之前的错误页面,就会出现如下效果:

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

类似这里如果我们没有输入正确的数据信息,就会显示" Login Failed"

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

POST请求如何写代码,我们还是先在360浏览器抓包数据分析一下,再去考虑。

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

在Android下编写代码实现POST请求,如下:

步骤:

•//重要,记得设置请求方式post
  conn.setRequestMethod("POST");
•//重要,记得设置数据的类型
  conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
 String data = "qq="+qq+"&password="+pwd;
•//重要,记得设置数据的长度
 conn.setRequestProperty("Content-Length", String.valueOf(data.length()));

•//重要,记得给服务器写数据
 conn.setDoOutput(true);//声明要给服务器写数据
•//重要,把数据写给服务器
 conn.getOutputStream().write(data.getBytes());

(1)MainActivity.java:

 package com.himi.post;

 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() {
//post请求提交数据
//String path = "http://localhost:8080/web/LoginServlet";这里不能写成localhost
try {
String path = getString(R.string.serverip);
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//重要,记得设置请求方式post
conn.setRequestMethod("POST");
//重要,记得设置数据的类型
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
String data = "qq="+qq+"&password="+pwd;
//重要,记得设置数据的长度
conn.setRequestProperty("Content-Length", String.valueOf(data.length())); //重要,记得给服务器写数据
conn.setDoOutput(true);//声明要给服务器写数据
//重要,把数据写给服务器
conn.getOutputStream().write(data.getBytes()); 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() { public void run() {
Toast.makeText(MainActivity.this, text, 0).show(); }
});
}
}

工具类还是StreamTools,如下:

 package com.himi.post;

 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; }
}

 

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

布局效果图如下:

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

(3)布署程序到手机上如下:

当我们输入错误的QQ账号或密码时候,如下:

输入QQ账号:10000,QQ密码:123123,结果如下;

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

当我们输入QQ账号或者密码是正确的时候:

比如,我们输入QQ账号:10086,输入密码:123456,结果如下:

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

同时服务器端也出现了数据接收的记录,如下:

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