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

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,结果如下:

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

时间: 2024-12-17 15:13:28

Android(java)学习笔记210:采用post请求提交数据到服务器的相关文章

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

1.GET请求:    组拼url的路径,把提交的数据拼装url的后面,提交给服务器. 缺点:(1)安全性  (2)长度有限不能超过4K(http协议限制),IE浏览器限制至1K 优点:代码方便编写 2.我们首先在电脑模拟下访问服务器的场景 (1)使用Eclipse 新建一个 " 动态web项目 ",如下: (2)然后编写一个servlet程序(运行在服务端),命名为" LoginServlet ",如下: 代码内容如下: 1 package com.himi.we

Android 采用post方式提交数据到服务器

接着上篇<Android 采用get方式提交数据到服务器>,本文来实现采用post方式提交数据到服务器 首先对比一下get方式和post方式: 修改布局: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="m

Android 采用get方式提交数据到服务器

首先搭建模拟web 服务器,新建动态web项目,servlet代码如下: package com.wuyudong.web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet

Java学习笔记之[ 利用扫描仪Scanner进行数据输入 ]

/*********数据的输入********//**利用扫描仪Scanner进行数据输入 怎么使用扫描仪Scanner *1.放在类声明之前,引入扫描仪 import java.util.Scanner; *2.声明一个新的扫描仪(即向内存申请一个空间) Scanner in *3.赋值 in=new Scanner(System.in); Scanner in=new Scanner(System.in); *4.使用扫描仪 整形数据输入:in.nextInt()来接收 双精度小数输入:in

Android提交数据到服务器的两种方式四种方法

Android应用开发中,会经常要提交数据到服务器和从服务器得到数据,本文主要是给出了利用http协议采用HttpClient方式向服务器提交数据的方法. /** * @author Dylan * 本类封装了Android中向web服务器提交数据的两种方式四种方法 */ public class SubmitDataByHttpClientAndOrdinaryWay { /** * 使用get请求以普通方式提交数据 * @param map 传递进来的数据,以map的形式进行了封装 * @p

java/android 设计模式学习笔记(14)---外观模式

这篇博客来介绍外观模式(Facade Pattern),外观模式也称为门面模式,它在开发过程中运用频率非常高,尤其是第三方 SDK 基本很大概率都会使用外观模式.通过一个外观类使得整个子系统只有一个统一的高层的接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节.当然,在我们的开发过程中,外观模式也是我们封装 API 的常用手段,例如网络模块.ImageLoader 模块等.其实我们在开发过程中可能已经使用过很多次外观模式,只是没有从理论层面去了解它. 转载请注明出处:http://bl

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程.一个复杂的对象有大量的组成部分,比如汽车它有车轮.方向盘.发动机.以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过

java/android 设计模式学习笔记(16)---命令模式

这篇博客我们来介绍一下命令模式(Command Pattern),它是行为型设计模式之一.命令模式相对于其他的设计模式更为灵活多变,我们接触比较多的命令模式个例无非就是程序菜单命令,如在操作系统中,我们点击关机命令,系统就会执行一系列的操作,如先是暂停处理事件,保存系统的一些配置,然后结束程序进程,最后调用内核命令关闭计算机等,对于这一系列的命令,用户不用去管,用户只需点击系统的关机按钮即可完成如上一系列的命令.而我们的命令模式其实也与之相同,将一系列的方法调用封装,用户只需调用一个方法执行,那

java/android 设计模式学习笔记(2)---观察者模式

这篇来讲一下观察者模式,观察者模式在实际项目中使用的也是非常频繁的,它最常用的地方是GUI系统.订阅--发布系统等.因为这个模式的一个重要作用就是解耦,使得它们之间的依赖性更小,甚至做到毫无依赖.以GUI系统来说,应用的UI具有易变性,尤其是前期随着业务的改变或者产品的需求修改,应用界面也经常性变化,但是业务逻辑基本变化不大,此时,GUI系统需要一套机制来应对这种情况,使得UI层与具体的业务逻辑解耦,观察者模式此时就派上用场了. PS:对技术感兴趣的同鞋加群544645972一起交流. 设计模式