这篇文章我们共同来学习HttpUrlConnection以及HttpClient.
首先,我们来了解一下通过Http协议,Android APP客户端与服务器交互的基本知识
客户端->服务器:客户端向服务器发送请求主要包含以下信息:请求的Url地址、请求头以及可选的请求体
服务器->客户端:服务器接收到客户端发来的请求后,会进行相应的处理,并向客户端输出信息,输出的信息包含响应头和响应体。
Http协议支持的操作有GET、POST、HEAD、PUT、TRACE、OPTIONS、DELETE,其中最常用的还是GET和POST。
GET vs POST
GET:
1、GET请求可以被缓存
2、当用GET请求发送键值对时,键值对会随着URL一起发送的
3、GET请求的安全性很低,不能用GET请求发送敏感的信息
4、GET请求发送数据是有长度限制的(URL不能超过2048个字符)
5、由于GET请求较低的安全性,我们不应该用GET请求去执行增加、删除、修改等操作,应该只用它来获取数据
POST:
1、POST请求从不会被缓存
2、POST请求的URL中追加键值对参数,这些键值对参数不是随着URL发送的,而是被放入到请求体中发送的
3、应该用POST请求发送敏感信息,而不是用GET
4、理论上POST请求不存在发送数据大小的限制
5、当执行增加、删除、修改等操作时,应该使用POST请求,而不应该使用GET请求
HttpURLConnection vs HttpClient
在Android 2.2版本以及之前的版本使用HttpClient是较好的选择,而在Android 2.3版本以及以后的版本,HttpURLConnection则是最佳的选择。
原因:Android 2.2之前(包括2.2),HttpURLConnection一直存在着一些令人厌烦的bug。而HttpClient是Apache用于发送http请求的客户端,其提供了强大的API支持,而且基本没有什么bug。
Android 2.2之后,HttpURLConnection的bug得到解决,并且其API简单,体积较小,也能够满足大部分的需求,因此非常适合Android项目。相反,HttpClient由于其太过复杂,Android团队在保持向后兼容的情况下,很难对其进行增强,另外从Android 6.0版本开始,HttpClient库被移除了。
HttpURLConnection使用
GET方式:
private HttpURLConnection getHttpURLConnection(String url) { HttpURLConnection httpURLConnection = null; try { URL mUrl = new URL(url); httpURLConnection = (HttpURLConnection) mUrl.openConnection(); httpURLConnection.setConnectTimeout(15000); //设置连接超时时间 httpURLConnection.setReadTimeout(15000); //设置读取超时时间 httpURLConnection.setRequestMethod("GET"); //设置请求参数,也可以不设置,默认为GET httpURLConnection.setRequestProperty("Connection", "Keep-Alive"); //添加Header httpURLConnection.setDoInput(true); //接收输入流。httpURLConnection默认也支持从服务端读取结果流,所以此设置也可以省略 httpURLConnection.setDoOutput(true); } catch (IOException e) { e.printStackTrace(); } return httpURLConnection; }
public void useHttpUrlConnectionGet(String url) { InputStream inputStream = null; HttpURLConnection httpURLConnection = getHttpURLConnection(url); try { httpURLConnection.connect(); //通过调用connect方法建立TCP连接,但是并未真正获取数据。该方法也不必显式调用,当调用getInputStream方法时内部也会自动调用connect方法的 inputStream = httpURLConnection.getInputStream(); //调用getInputStream方法后,服务端才会收到请求,并阻塞式地接收服务端返回的数据 int code = httpURLConnection.getResponseCode(); String response = converStreamToString(inputStream); Log.i("Debug", "请求状态码:" + code + "\n请求结果\n" + response); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } }
private String converStreamToString(InputStream is) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuffer sb = new StringBuffer(); String line = null; while((line = reader.readLine()) != null) { sb.append(line + "\n"); } String response = sb.toString(); return response; }
POST方式:
private HttpURLConnection getHttpURLConnection(String url) { HttpURLConnection httpURLConnection = null; try { URL mUrl = new URL(url); httpURLConnection = (HttpURLConnection) mUrl.openConnection(); httpURLConnection.setConnectTimeout(15000); //设置连接超时时间 httpURLConnection.setReadTimeout(15000); //设置读取超时时间 httpURLConnection.setRequestMethod("POST"); //设置请求参数 httpURLConnection.setRequestProperty("Connection", "Keep-Alive"); //添加Header httpURLConnection.setDoInput(true); //接收输入流。httpURLConnection默认也支持从服务端读取结果流,所以此设置也可以省略 httpURLConnection.setDoOutput(true); } catch (IOException e) { e.printStackTrace(); } return httpURLConnection; }
private void postParams(OutputStream outputStream, List<NameValuePair>paramsList) throws IOException { StringBuilder stringBuilder = new StringBuilder(); for (NameValuePair pair:paramsList) { if (!TextUtils.isEmpty(stringBuilder)) { stringBuilder.append("&"); } stringBuilder.append(URLEncoder.encode(pair.getName(), "UTF-8")); stringBuilder.append("="); stringBuilder.append(URLEncoder.encode(pair.getValue(), "UTF-8")); } BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8")); writer.write(stringBuilder.toString()); writer.flush(); writer.close(); }
private String converStreamToString(InputStream is) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuffer sb = new StringBuffer(); String line = null; while((line = reader.readLine()) != null) { sb.append(line + "\n"); } String response = sb.toString(); return response; }
public void useHttpUrlConnectionPost(String url) { InputStream inputStream = null; HttpURLConnection httpURLConnection = getHttpURLConnection(url); List<NameValuePair> postParams = new ArrayList<>(); //要传递的参数 postParams.add(new BasicNameValuePair("username", "moon")); postParams.add(new BasicNameValuePair("password", "123")); try { postParams(httpURLConnection.getOutputStream(), postParams); httpURLConnection.connect(); //通过调用connect方法建立TCP连接,但是并未真正获取数据。该方法也不必显式调用,当调用getInputStream方法时内部也会自动调用connect方法的 inputStream = httpURLConnection.getInputStream(); //调用getInputStream方法后,服务端才会收到请求,并阻塞式地接收服务端返回的数据 int code = httpURLConnection.getResponseCode(); String response = converStreamToString(inputStream); Log.i("Debug", "请求状态码:" + code + "\n请求结果\n" + response); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } }
HttpClient使用
private String converStreamToString(InputStream is) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuffer sb = new StringBuffer(); String line = null; while((line = reader.readLine()) != null) { sb.append(line + "\n"); } String response = sb.toString(); return response; }
private HttpClient createHttpClient() { HttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 15000); //设置连接超时时间 HttpConnectionParams.setSoTimeout(httpParams, 15000); //设置请求超时时间 HttpConnectionParams.setTcpNoDelay(httpParams, true); HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8); HttpProtocolParams.setUseExpectContinue(httpParams, true); //持续握手 HttpClient httpClient = new DefaultHttpClient(httpParams); return httpClient; }
GET方式:
public void useHttpClientGet(String url) { HttpGet httpGet = new HttpGet(url); httpGet.addHeader("Connection", "Keep-Alive"); HttpClient httpClient = createHttpClient(); try { HttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); int code = httpResponse.getStatusLine().getStatusCode(); if (null != httpEntity) { InputStream inputStream = httpEntity.getContent(); String response = converStreamToString(inputStream); Log.i("Debug", "请求状态码:" + code + "\n请求结果:\n" + response); inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } }POST方式:
private void useHttpClientPost(String url) { HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Connection", "Keep-Alive"); HttpClient httpClient = createHttpClient(); List<NameValuePair> postParams = new ArrayList<>(); //要传递的参数 postParams.add(new BasicNameValuePair("username", "moon")); postParams.add(new BasicNameValuePair("password", "123")); try { httpPost.setEntity(new UrlEncodedFormEntity(postParams)); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); int code = httpResponse.getStatusLine().getStatusCode(); if (null != httpEntity) { InputStream inputStream = httpEntity.getContent(); String response = converStreamToString(inputStream); Log.i("Debug", "请求状态码:" + code + "\n请求结果:\n" + response); inputStream.close(); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }