zoukankan      html  css  js  c++  java
  • android学习笔记----记录get、post方式提交以及抓包和乱码问题

    目录

    MyEclipse中的代码:

    post方式和get方式提交区别:

    将服务器的返回数据展示到Toast上:

    Android Studio中的代码:

    关于中文乱码问题:


    用tomcat服务器:

    MyEclipse中的代码:

    LoginServlet.java

    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;
    
    	@Override
    	protected void doGet(HttpServletRequest request,
    			HttpServletResponse response) throws ServletException, IOException {
    		String name = request.getParameter("username");
    		String pwd = request.getParameter("password");
    		System.out.println("username~~"
    				+ new String(name.getBytes("iso-8859-1"), "utf-8"));
    		System.out.println("password~~" + pwd);
    		if ("abc".equals(name) && "123".equals(pwd)) {
    			response.getOutputStream().write("success".getBytes()); // gbk
    		} else {
    			response.getOutputStream().write("login fail".getBytes());
    		}
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		System.out.println("post方式提交数据");
    		doGet(request, response);
    	}
    }

    login.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/htm14/loose.dtd">
    <html>
    <head>
    
    <title>login</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <!--
    	<link rel="stylesheet" type="text/css" href="styles.css">
    	-->
    </head>
    
    <body>
    	<form action="/login/LoginServlet">
    		<br>使用get方式提交数据到服务器<br> <br>用户名<br> <input
    			type="text" name="username"> <br>密码<br> <input
    			type="password" name="password"> <br> <input
    			type="submit">
    	</form>
    	<form action="/login/LoginServlet" method="post">
    		<br> <br> <br> <br>使用post方式提交数据到服务器<br> <br>用户名<br>
    		<input type="text" name="username"> <br>密码<br> <input
    			type="password" name="password"> <br> <input
    			type="submit">
    	</form>
    </body>
    </html>
    

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
      <display-name></display-name>
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
      <servlet>
      <servlet-name>login</servlet-name>
      <servlet-class>com.itheima.login.LoginServlet</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>login</servlet-name>
      	<url-pattern>/LoginServlet</url-pattern>
      </servlet-mapping>
    </web-app>

    然后在浏览器输入:http://localhost:8080/login/login.jsp

    效果如下:

    post方式和get方式提交区别:

    post方式和get方式提交对比(IE浏览器用httpwatch抓包,建议用chrome浏览器自带抓包):

    get方式提交:

          组拼url地址把数据组拼到url上,有大小限制1kb  4kb

    post方式提交:

          post方式提交安全,没有大小限制

    google chrome自带抓包:

    get提交方式:

     post提交方式:

    关于Http的基础知识和消息格式可以参考这些博客

    HTTP协议基础及报文抓包分析:

    http://baijiahao.baidu.com/s?id=1596966404370818881&wfr=spider&for=pc

    HTTP协议简介——HTTP协议基础知识学习:

    https://www.cnblogs.com/ranyonsue/p/5984001.html

    将服务器的返回数据展示到Toast上:

    get方式(默认)提交数据效果图:

    post方式提交数据效果图:

    Android Studio中的代码:

    MainActivity.java

    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLEncoder;
    
    public class MainActivity extends AppCompatActivity {
    
        private EditText et_username;
        private EditText et_password;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            et_username = (EditText) findViewById(R.id.et_username);
            et_password = (EditText) findViewById(R.id.et_password);
        }
    
        // 点击按钮进行get方式提交数据
        public void click1(View view) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        System.getProperties().list(System.out);
                        Log.d("MainActivty", "??");
                        // 获取用户名和密码
                        String name = et_username.getText().toString().trim();
                        String pwd = et_password.getText().toString().trim();
                        // 定义get方式要提交的路径,如果要提交中文,记得对name和pwd进行一个urlencode编码
                        // 如果不编码,服务器可能接收不到POST提交数据或者接收到中文乱码
                        String path = "http://192.168.164.1:8080/login/LoginServlet?username=" + URLEncoder.encode(name, "utf-8") + "&password=" + URLEncoder.encode(pwd, "utf-8");
                        URL url = new URL(path);
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        conn.setRequestMethod("GET");
                        conn.setConnectTimeout(5000);
                        int code = conn.getResponseCode();
                        if (code == 200) {
                            InputStream inputStream = conn.getInputStream();
                            // 把inputstream转换成String
                            String content = StreamTools.readStream(inputStream);
    
                            // 把服务器的数据展示到Toast,不能在子线程展示
                            showToast(content);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    
        // 点击按钮进行post方式提交数据
        public void click2(View view) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        // 获取用户名和密码
                        String name = et_username.getText().toString().trim();
                        String pwd = et_password.getText().toString().trim();
                        // 定义post方式要提交的路径,如果要提交中文,记得对name和pwd进行一个urlencode编码
                        // 如果不编码,服务器可能接收不到POST提交数据或者接收到中文乱码
                        // 因为这里不编码,那么请求头信息Content-Length是要data.length()无法确定,长度不确定或者不一致了,导致奇怪的问题
                        String data = "username=" + URLEncoder.encode(name, "utf-8") + "&password=" + URLEncoder.encode(pwd, "utf-8"); // 请求体的内容
                        // 一========和get方式提交数据区别1 路径不同
                        String path = "http://192.168.164.1:8080/login/LoginServlet";
                        URL url = new URL(path);
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        // 二========和get方式提交数据区别2 设置请求方式是post
                        conn.setRequestMethod("POST");
                        conn.setConnectTimeout(5000);
                        // 三========和get方式提交数据区别3 要多设置2个请求头信息
                        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                        conn.setRequestProperty("Content-Length", Integer.toString(data.length()));
                        // 四 把我们组拼好的数据提交给服务器,以流的形式提交
                        conn.setDoOutput(true); // 设置一个标记,允许输出
                        conn.getOutputStream().write(data.getBytes());
                        int code = conn.getResponseCode();
                        if (code == 200) {
                            InputStream inputStream = conn.getInputStream();
                            // 把inputstream转换成String
                            String content = StreamTools.readStream(inputStream);
                            // 把服务器的数据展示到Toast,不能在子线程展示
                            showToast(content);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    
        public void showToast(final String content) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // 该方法切换到主线程,一定在主线程执行
                    Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    

    批注:setDoOutput方法和setRequestProperty方法是HttpURLConnection的父类URLConnection中的方法

    public void setDoOutput (boolean dooutput)

       doOutput字段用于此URLConnection到指定的值。

    URL连接可用于输入和/或输出。如果要将URL连接用于输出,则将DoOutput标志设置为true;如果不使用URL连接,则设置为false。默认值为假。

    public void setRequestProperty (String key, String value)

          设置常规请求属性。如果具有键的属性已经存在,则用新值覆盖其值。

    注意:http要求所有合法拥有具有相同键的多个实例的请求属性使用逗号分隔的列表语法,该语法允许将多个属性追加到单个属性中。

    参数:

        key:请求的关键字(例如,“Accept").

        value:与之相对应的值

        HTTP请求报文的请求头由key/value对组成,每行为一对,key和value之间通过冒号(:)+空格(sp)分割。请求头的作用主要用于通知服务端有关于客户端的请求信息。

    值得一提的是,使用GET方式只能提交不超过128字节的数据。使用POST报文时,用户可以向服务器请求一个Web页面,但Web页面的特定内容依赖于用户在表单字段中输入的内容,该内容将放在请求体中。当使用GET方法时,在URL字段中包括输入的数据,而请求体为空。

             如果要提交中文,记得对name和pwd进行一个urlencode编码
             如果不编码,服务器可能接收不到POST提交数据或者接收到中文乱码

    StreamTools.java

    import java.io.BufferedInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class StreamTools {
        // 把一个inputstream 转换成一个String
        public static String readStream(InputStream in) throws IOException {
            BufferedInputStream bis = new BufferedInputStream(in);
            // 定义一个内存输出流
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int len;
            byte[] buffer = new byte[8192];
            while ((len = bis.read(buffer, 0, 8192)) != -1) {
                baos.write(buffer, 0, len);
            }
            bis.close();
            // 可以直接baos.toString();这样写方便指定第二个参数编码表
            // 因为服务器默认是用gbk了,这里第二个参数用gbk,否则解码城乱码
            // 或者服务器传输流数据时是用"success".getBytes("utf-8")编码成utf-8形式,第二个参数就可以不写,android默认是utf-8
            String content = new String(baos.toByteArray(), "gbk");
            return content;
        }
    }
    

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <EditText
            android:id="@+id/et_username"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入用户名" />
    
        <EditText
            android:id="@+id/et_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入密码" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click1"
            android:text="get" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click2"
            android:text="post" />
        
    </LinearLayout>

    关于中文乱码问题:

    可能服务器端编写的时候用的编码表是gbk,而android端默认是utf-8

    这样要么服务器解决编码问题,要么android端解决解码问题

    服务器端解决如图:

    或者服务器不改成utf-8仍然用gbk编码,让android端改为gbk解码:

    Android端解决如下:

    这样,中文的“成功”就能正确显示了

    android端用户名提交中文的时候,只要记得用URLEncoder类的encode方法编码就行了,这样post方式提交也能收到中文。

    =================================Talk is cheap, show me the code===============================

    CSDN博客地址:https://blog.csdn.net/qq_34115899
  • 相关阅读:
    Java 异常
    【转】Java 内部类总结
    【转】Java中的static关键字解析
    【转】事务及事务隔离级别
    【转】事务并发的问题
    【转】hibernate对象三种状态
    iOS指南针
    CoreLocation 定位
    swift 2.2 语法 (下)
    swift 2.2 语法 (中)
  • 原文地址:https://www.cnblogs.com/lcy0515/p/10807880.html
Copyright © 2011-2022 走看看