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.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,结果如下:
同时服务器端也出现了数据接收的记录,如下: