Android 网络中get与post两种提交数据的方式
2017-04-17 13:36
387 查看
项目简介:
该项目演示android中的两种网络请求方式:get与post详细介绍:
该项目中有六个按钮,共有三种框架分别饰演GET和POST提交数据的方式,并获得从服务器返回的数据(类似与登录界面)如下图所示,在两个输入框内输入数据后,点击第一个按钮,输入框中的数据会提交给服务器,如果输入的数据正确,则如下所示:
如果输入的数据不正确,就如下所示:
其余的按钮都一样,只是提交的方式或者使用的框架不一定。基本操作都是提交数据给服务器,然后服务器返回数据。
该应用涉及到的知识有:
1.POST提交与GET提交的区别GET直接把需要提交的数据凭借在URL后面。
POST把需要提交的数据封装在请求正文中,并且在请求头中要多出两行属性Content-type和Content-Lenght。
2.使用HttpURLConnection框架来实现get和post的提交
3.使用HttpClient框架来实现get和post的提交
4.使用AsyncHttpClient框架来实现get和post的提交
5.解决服务器与客户端之间的乱码问题
注意:
1.需要自己在Tomcat上新建一个web项目,然后在web项目中新建一个servlet。最好现在网页上实验数据能够提交,再在Android上实现。2.post方式提交失败,即在请求码获取的时候总是抛出错误,可能是使用setRequestProperty设置Content-type和Content-Lenght时属性出错导致的
3.对于Android 6.0以后,HttpClient框架已经移除,官方推荐使用HttpURLConnection,因为后者的效率更高。如果要想在Android 6.0 以后使用HttpClient,需要在自己的项目下添加org.apache.http.legacy.jar(点击到下载界面),即可使用,
4.对于中文乱码的问题,要注意到一点,服务器默认使用iso8859-1,windows平台默认使用gbk,而Android系统使用utf-8,所以在编写服务器的servlet的时候一定要注意将中文先解码在编码
步骤:
1.准备工作
1.1由于涉及到服务器,所以新建一个Dynamic Web Project,这里命名为Nweb。
1.2 在Src目录下创建一个包,在创建一个Servlet,这里命名为LoginServlet:
import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 浏览器(Android手机的浏览器)提交数据是会把中文用utf-8提交到服务器 // 服务器会使用iso8859-1解析数据 // 浏览器提交的编码与服务器的解码不一致,会导致中文乱码 String name = request.getParameter("name"); String password = request.getParameter("password"); // 在控制台上输出信息,便于开发 System.out.println("没有处理之前 姓名:" + name + " 用户:" + password); // 中文会乱码,所以先用iso8859-1把字符串解码成字节数组,然后在用utf-8编码成字符串 name = new String(name.getBytes("iso8859-1"), "utf-8"); // 在控制台上输出信息,便于开发 System.out.println("处理后 姓名:" + name + " 用户:" + password); // 获取输出流,用来给客户端返回信息 OutputStream os = response.getOutputStream(); // 这里应当连接数据库,进行查询语句,这里直接判断了,不连接数据库了 if ("hhh".equals(name) && "123".equals(password)) { // 注意,要写上编码格式,不然windows系统下默认为gbk,而Android客户端默认是utf-8,这样会导致乱码。 os.write((name + " 登录成功").getBytes("utf-8")); } else if ("张三".equals(name) && "123".equals(password)) { os.write((name + " 登录成功").getBytes("utf-8")); } else { os.write(("你总是登录不上,还要这手机干什么?摔了吧,换个新的就登上了").getBytes("utf-8")); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
这个Servlet的作用就是判断输入的两个数据(姓名name和密码password)是否符合要求,符合就返回登录成功的信息,不符合就返回登录失败的信息。
1.3 在webRoot目录下创建一个login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>登录界面</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> get提交方式 <body> <form action="LoginServlet" method="get"> 用户名:<input type="text" name="name"><br> 密码:<input type="text" name="password"><br> <input type="submit" value="提交"> </form> </body> <br/> <br/> <
这个界面对Android项目没有任何作用,只是测试一下自己的LoginServlet写的是否正确
1.4部署在tomcat服务器上,开始测试
打开浏览器,输入http://10.12.16.141:8080/Nweb/login.jsp,出现如下界面:
在第一个表单下面正确填写数据,并点击上面的提交按钮后,显示登录成功的信息,然后会发现,浏览器里面的地址栏变成了了http://10.12.16.141:8080/Nweb/LoginServlet?name=%E5%BC%A0%E4%B8%89&password=123,其中%E5%BC%A0%E4%B8%89是中文经过编码后产生的数据。这里就得到了GET提交方式的路径格式了。
同样,利用第二个表单,得到POST提交方式的路径为http://10.12.16.141:8080/Nweb/LoginServlet,并且打开浏览器的开发者工具,可以看到请求表头中多了两行数据:
2.创建Android项目
2.1由于项目中使用了HttpCLinet框架,而在Android6.0后被移除了,所以要添加一个支持该框架的jar包(可以点击这里到下载地址)。在项目先新建一个libs文件夹,把支持包放进去进行了,点后对该包右击,选择Build path就完成了:
2.2 项目中使用了AsyncHttpClient,这是一个开源项目,是别人基于HttpClinet框架封装好的框架,比使用HttpClient更方便,下载地址点击这里(里面的readme.txt文件有详细说明)。使用该框架前,需要添加该矿建的源码包,并且也要添加支持HttpClinet框架的jar包:
3.布局文件
编写activity_mian.xml布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="hhh.exercise.ngetandpost.MainActivity" > <EditText android:id="@+id/et_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="张三" android:textColor="#00ff00" android:textSize="30sp" /> <requestFocus /> <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="123" android:textColor="#00ff00" android:textSize="30sp" /> <Button android:id="@+id/bt_1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="GET/HttpURLConnection" android:textColor="#ff0000" /> <Button android:id="@+id/bt_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="GET/HttpClient" android:textColor="#ff0000" /> <Button android:id="@+id/bt_3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="GET/AsyncHttpClient" android:textColor="#ff0000" /> <Button android:id="@+id/bt_4" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="POST/HttpURLConnection" android:textColor="#0000ff" /> <Button android:id="@+id/bt_5" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="POST/HttpClient" android:textColor="#0000ff" /> <Button android:id="@+id/bt_6" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="POST/AsyncHttpClient" android:textColor="#0000ff" /> </LinearLayout>
这里的布局就是从上到下,两个EditText,六个按钮。
2.Activity
编写MainActivity代码:
import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity implements< 10d8c /span> OnClickListener { private EditText ed_name; private EditText ed_password; // 创建一个静态的Context对象,因为Handler是静态的,而且使用到了Context对象,所以这里也要静态的 private static Context context; // 创建一个静态的Handler对象(静态的可以防止内存泄露,这里不用静态的也可以),用于输出从服务器返回的数据 public static Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 0: Toast.makeText(context, "读取流中数据出错", Toast.LENGTH_SHORT).show(); break; case 1: Toast.makeText(context, "出现未知错误", Toast.LENGTH_SHORT).show(); break; case 2: Toast.makeText(context, "无法连接网络,可能是响应码错误", Toast.LENGTH_SHORT).show(); break; case 3: // 吐司弹出服务器的数据 String result = (String) msg.obj; Toast.makeText(context, result, Toast.LENGTH_SHORT).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); context = getApplicationContext(); ed_name = (EditText) findViewById(R.id.et_name); ed_password = (EditText) findViewById(R.id.et_password); Button bt_1 = (Button) findViewById(R.id.bt_1); Button bt_2 = (Button) findViewById(R.id.bt_2); Button bt_3 = (Button) findViewById(R.id.bt_3); Button bt_4 = (Button) findViewById(R.id.bt_4); Button bt_5 = (Button) findViewById(R.id.bt_5); Button bt_6 = (Button) findViewById(R.id.bt_6); bt_1.setOnClickListener(this); bt_2.setOnClickListener(this); bt_3.setOnClickListener(this); bt_4.setOnClickListener(this); bt_5.setOnClickListener(this); bt_6.setOnClickListener(this); } @Override public void onClick(View v) { // 不同的按钮对应处理不同的操作。前三个分别使用不同的框架处理get请求。后三个分别使用不同的框架框架处理post请求 switch (v.getId()) { case R.id.bt_1: method_1(); break; case R.id.bt_2: method_2(); break; case R.id.bt_3: method_3(); break; case R.id.bt_4: method_4(); break; case R.id.bt_5: method_5(); break; case R.id.bt_6: method_6(); break; } } /* 创建一个方法,该方法传入一个输入流,读取流中的书,然后把数据转化为字节数组返回 */ private byte[] getDataFromStream(InputStream is) { try { byte[] buffer = new byte[1024]; ByteArrayOutputStream bos = new ByteArrayOutputStream(); int len = 0; while ((len = is.read(buffer)) != -1) { bos.write(buffer, 0, len); bos.flush(); } byte[] result = bos.toByteArray(); is.close(); bos.close(); return result; } catch (Exception e) { // 发送数据给主线程,告诉主线程读取流的时候出错 handler.sendEmptyMessage(0); e.printStackTrace(); } return null; } /** 使用HttpURLConnection框架发送get请求 */ private void method_1() { // 按钮太多,这里出一个吐司,告诉用户使用的是HttpURLConnection发送GET请求 Toast.makeText(getApplicationContext(), "HttpURLConnection GET", Toast.LENGTH_SHORT).show(); // 获取输入框中的信息 String name = ed_name.getText().toString(); String password = ed_password.getText().toString(); // 拼接servlet的URL地址.注意,如果提交的数据有中文,需要处理后在凭借。 // 提交的数据需要经过URL编码,英文和数字编码后保持不变,中文会变。 // URLEncoder.encode(name):该编码默认使用utf-8编码。如果要改变,可以使用它的重载方法 // 也可以编码成其他格式,但是必须要与服务器保持编码统一。 final String path = "http://10.12.16.141:8080/Nweb/LoginServlet?name=" + URLEncoder.encode(name) + "&password=" + password; // 开启子线程,进行数据的传入 new Thread(new Runnable() { @Override public void run() { try { URL url = new URL(path); // 获取HttpURLConnection对象 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置连接属性并连接 conn.setReadTimeout(5000); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); conn.connect(); // 判断响应码 if (conn.getResponseCode() == 200) { InputStream is = conn.getInputStream(); // 读取流中的数据 byte[] data = getDataFromStream(is); String result = new String(data, "UTF-8"); Message msg = handler.obtainMessage(); msg.what = 3; msg.obj = result; handler.sendMessage(msg); } else { handler.sendEmptyMessage(2); } } catch (Exception e) { handler.sendEmptyMessage(1); e.printStackTrace(); } finally { } } }).start(); } /** 使用HttpClinet框架提交get请求 */ private void method_2() { Toast.makeText(getApplicationContext(), "HttpClinet GET", Toast.LENGTH_SHORT).show(); String name = ed_name.getText().toString(); String password = ed_password.getText().toString(); final String path = "http://10.12.16.141:8080/Nweb/LoginServlet?name=" + URLEncoder.encode(name) + "&password=" + password; // 开启子线程,进行数据的传入 new Thread(new Runnable() { @Override public void run() { try { // 1.创建HttpClient对象 HttpClient client = new DefaultHttpClient(); // 2.获取HttpGet HttpGet httpGet = new HttpGet(path); // 3.使用HttpClient将HttpGet发送出去(即使用客户端对象将get请求发送出去),得到HttpResponse HttpResponse response = client.execute(httpGet); // 4.拿到状态行 StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() == 200) { // 拿到相应实体 HttpEntity entity = response.getEntity(); // 拿到输入流 InputStream is = entity.getContent(); byte[] data = getDataFromStream(is); String result = new String(data, "UTF-8"); Message msg = handler.obtainMessage(); msg.what = 3; msg.obj = result; handler.sendMessage(msg); } else { handler.sendEmptyMessage(2); } } catch (Exception e) { handler.sendEmptyMessage(1); e.printStackTrace(); } finally { } } }).start(); } /** 使用自定义的高度封装的AsyncHttpClient框架提交get请求 */ private void method_3() { Toast.makeText(getApplicationContext(), "AsyncHttpClient GET", Toast.LENGTH_SHORT).show(); String name = ed_name.getText().toString(); String password = ed_password.getText().toString(); final String path = "http://10.12.16.141:8080/Nweb/LoginServlet?name=" + URLEncoder.encode(name) + "&password=" + password; // 1.创建异步HttpClient AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); // 2.发送get请求 // 第一个参数是URL对象 // 第二个参数为服务器返回的响应信息 asyncHttpClient.get(path, new GetResponserHandler()); } // 定义一个内部类,根据异步HttpClinet代码示例,该类继承AsyncHttpResponseHandler。该类的作用是用来处理get请求后服务器返回的信息 class GetResponserHandler extends AsyncHttpResponseHandler { // 请求服务器成功时(即状态码为200时,系统自动调用该方法) // 第三个参数 responseBody为服务器返回的信息 @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { Toast.makeText(MainActivity.this, new String(responseBody), 1).show(); } // 请求失败(即状态码不为200,系统调用此方法) @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Toast.makeText(MainActivity.this, "请求失败", 1).show(); } } /** 使用HttpURLConnection框架发送post请求 */ private void method_4() { Toast.makeText(getApplicationContext(), "HttpURLConnection POST", Toast.LENGTH_SHORT).show(); final String name = ed_name.getText().toString(); final String password = ed_password.getText().toString(); // 拼接servlet的URL地址。 final String path = "http://10.12.16.141:8080/Nweb/LoginServlet"; // 开启线程,进行数据的传输 new Thread(new Runnable() { @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(5000); conn.setConnectTimeout(5000); conn.setRequestMethod("POST"); // 拼接出要提交的数据的字符串 // 注意,如果提交的数据有中文,需要处理后再拼接。 // 提交的数据需要经过URL编码,英文和数字编码后保持不变,中文会变。 // URLEncoder.encode(name):该编码默认使用utf-8编码。如果要改变,可以使用它的重载方法 String text = "name=" + URLEncoder.encode(name) + "&password=" + password; // 添加post请求的两行属性 // Content-Type: application/x-www-form-urlencoded conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // Content-Length: conn.setRequestProperty("Content-Length", text.length() + ""); // 设置打开输出流,并拿到输出流(一定要写这一句,不然无法向输出流中写入数据) conn.setDoOutput(true); OutputStream os = conn.getOutputStream(); // 将拼接的字符串写入请求正文中,即使用输出流往服务器提交数据 os.write(text.getBytes()); if (conn.getResponseCode() == 200) { InputStream is = conn.getInputStream(); // 从输入流获取数据 byte[] data = getDataFromStream(is); String result = new String(data, "utf-8"); Message message = handler.obtainMessage(); message.what = 3; message.obj = result; handler.sendMessage(message); } else { handler.sendEmptyMessage(2); } } catch (Exception e) { handler.sendEmptyMessage(1); e.printStackTrace(); } } }).start(); } /** 使用HttpClinet框架提交post请求 */ private void method_5() { Toast.makeText(getApplicationContext(), "HttpClinet POST", Toast.LENGTH_SHORT).show(); final String name = ed_name.getText().toString(); final String password = ed_password.getText().toString(); final String path = "http://10.12.16.141:8080/Nweb/LoginServlet"; new Thread(new Runnable() { @Override public void run() { // 1.创建客户端对象 HttpClient httpClient = new DefaultHttpClient(); // 2.创建post请求对象 HttpPost httpPost = new HttpPost(path); // 封装from表单要提交的数据 List<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>(); // 第一个参数是servlet中接收的数据的名称,第二个参数是android布局文件中提价的数据的名称 BasicNameValuePair basicNameValuePair = new BasicNameValuePair("name", name); list.add(basicNameValuePair); BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("password", password); list.add(basicNameValuePair2); try { // 需要提交的数据已经在集合中了,把集合传给实体对象,此处最好设置一下编码,不然可能导致中文乱码。 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "utf-8"); // 设置post请求对象的实体,其实即使把要提交的数据封装到post请求的输出流中 httpPost.setEntity(entity); // 3.使用客户端发送post请求 HttpResponse httpResponse = httpClient.execute(httpPost); // 获取响应码 if (httpResponse.getStatusLine().getStatusCode() == 200) { InputStream is = httpResponse.getEntity().getContent(); // 从输入流获取数据 byte[] data = getDataFromStream(is); String result = new String(data, "utf-8"); Message message = handler.obtainMessage(); message.what = 3; message.obj = result; handler.sendMessage(message); } else { handler.sendEmptyMessage(2); } } catch (Exception e) { handler.sendEmptyMessage(1); e.printStackTrace(); } } }).start(); } /** 使用自定义的高度封装的AsyncHttpClient框架提交post请求 */ private void method_6() { Toast.makeText(getApplicationContext(), "AsyncHttpClient POST", Toast.LENGTH_SHORT).show(); String name = ed_name.getText().toString(); String password = ed_password.getText().toString(); final String path = "http://10.12.16.141:8080/Nweb/LoginServlet"; // 1.创建异步HttpClinet AsyncHttpClient client = new AsyncHttpClient(); // 封装要提交的数据 RequestParams params = new RequestParams(); params.put("name", name); params.put("password", password); // 2.发送post请求 client.post(path, params, new PostResponseHandler()); } // 定义一个内部类,根据异步HttpClinet代码示例,该类继承AsyncHttpResponseHandler。该类的作用是用来处理Post请求后服务器返回的信息 class PostResponseHandler extends AsyncHttpResponseHandler { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { Toast.makeText(MainActivity.this, new String(responseBody), 1).show(); } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Toast.makeText(MainActivity.this, "请求失败", 1).show(); } } }
整个应用完成
相关文章推荐
- Android-网络提交数据get和post的两种方式
- Android网络数据之向服务器提交数据的三种方式(get+post+AsyncHttpClient)
- [Android开发]Android之使用HTTP的get,post,HttpClient三种方式向服务器端提交文本数据
- Android传统HTTP请求get----post方式提交数据(包含乱码问题)
- Java基础知识强化之网络编程笔记18:Android网络通信之 使用HttpClient的Post / Get 方式读取网络数据(基于HTTP通信技术)
- Android之用HTTP的get,post,HttpClient三种方式向service提交文本数据
- Android网络编程之使用post方式提交数据
- Android之用HTTP的get,post,HttpClient三种方式向service提交文本数据
- Androidx学习笔记(36)---网络提交数据的方式--GET方式提交数据
- iOS 网络请求数据两种请求方式GET,POST
- Android -- 提交数据到服务器,Get Post方式, 异步Http框架提交
- Android -- 提交数据到服务器,Get Post方式, 异步Http框架提交
- Android之使用HTTP的get,post,HttpClient三种方式向服务器端提交文本数据
- Androidx学习笔记(37)--- 网络提交数据的方式--POST方式提交数据
- Android(java)学习笔记213:开源框架post和get方式提交数据(qq登录案例)
- android 通过get,post方式提交数据给服务器
- 程序使用 HTTP 协议和服务器交互主要是进行数据的提交,通常数据的提交是通过 GET 和 POST 两种方式来完成
- Android--向服务器提交数据的两种方法Post和Get
- 在线程中使用HttpClicent获取网络数据(get和post两种方式)
- 【Android】使用http的Post和Get方式获取网络数据