1.POST请求:
数据是以流的方式写给服务器
优点:(1)比较安全 (2)长度不限制
缺点:编写代码比较麻烦
2.我们首先在电脑模拟下POST请求访问服务器的场景:
我们修改之前编写的login.jsp代码,如下:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>??????? GET方式提交数据
POST方式提交数据
将修改过的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 //重要,记得设置请求方式post104 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 * 显示土司 在主线程更新UI135 * @param text136 */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 is15 * @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文件如下:
18 9 13 14 20 21 27 28 34 35 42
布局效果图如下:
(3)布署程序到手机上如下:
当我们输入错误的QQ账号或密码时候,如下:
输入QQ账号:10000,QQ密码:123123,结果如下;
当我们输入QQ账号或者密码是正确的时候:
比如,我们输入QQ账号:10086,输入密码:123456,结果如下:
同时服务器端也出现了数据接收的记录,如下: