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

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服务器上运行,如下:

我们在"POST方式提交数据"一栏,输入正确的QQ 账号和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);
    }

}

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

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

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

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

在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:

  1 package com.himi.post;
  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                 //post请求提交数据
 98                 //String path = "http://localhost:8080/web/LoginServlet";这里不能写成localhost
 99                 try {
100                     String path = getString(R.string.serverip);
101                     URL url = new URL(path);
102                     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
103                     //重要,记得设置请求方式post
104                     conn.setRequestMethod("POST");
105                     //重要,记得设置数据的类型
106                     conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
107                     String data = "qq="+qq+"&password="+pwd;
108                     //重要,记得设置数据的长度
109                     conn.setRequestProperty("Content-Length", String.valueOf(data.length()));
110                     
111                     //重要,记得给服务器写数据
112                     conn.setDoOutput(true);//声明要给服务器写数据
113                     //重要,把数据写给服务器
114                     conn.getOutputStream().write(data.getBytes());
115                     
116                     int code = conn.getResponseCode();
117                     if(code == 200) {
118                         InputStream is = conn.getInputStream();
119                         String result = StreamTools.readStream(is);
120                         showToastInAnyThread(result);
121                     }else {
122                         showToastInAnyThread("请求失败");
123                     }
124                 } catch (Exception e) {
125                     e.printStackTrace();
126                     showToastInAnyThread("请求失败");
127                 }
128             };
129         }.start();
130         
131     }
132     
133     /**
134      * 显示土司 在主线程更新UI
135      * @param text
136      */
137     public void showToastInAnyThread(final String text) {
138         runOnUiThread(new Runnable() {
139             
140             public void run() {
141                 Toast.makeText(MainActivity.this, text, 0).show();
142                 
143             }
144         });
145     }
146 }

工具类还是StreamTools,如下:

 1 package com.himi.post;
 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 }

 

(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账号或密码时候,如下:

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

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

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

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

原文地址:https://www.cnblogs.com/hebao0514/p/4783469.html