Android HttpClient HttpUrlConnection用法总结
来源:互联网 发布:淘宝网红棉太极棉鞋 编辑:程序博客网 时间:2024/06/07 06:52
HttpClient
这个不用说了,Apache的API,但是不推荐使用了,在最新的api中甚至都把HttpClient去掉了。但是还是有必要掌握下HttpClient的用法的
GET方式
//先将参数放入List,再对参数进行URL编码List<BasicNameValuePair> params = new LinkedList<BasicNameValuePair>();params.add(new BasicNameValuePair("param1", "中国"));params.add(new BasicNameValuePair("param2", "value2"));//对参数编码String param = URLEncodedUtils.format(params, "UTF-8");//baseUrl String baseUrl = "http://ubs.free4lab.com/php/method.php";//将URL与参数拼接HttpGet getMethod = new HttpGet(baseUrl + "?" + param);HttpClient httpClient = new DefaultHttpClient();try { HttpResponse response = httpClient.execute(getMethod); //发起GET请求 Log.i(TAG, "resCode = " + response.getStatusLine().getStatusCode()); //获取响应码 Log.i(TAG, "result = " + EntityUtils.toString(response.getEntity(), "utf-8"));//获取服务器响应内容} catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace();} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
POST方法
//和GET方式一样,先将参数放入Listparams = new LinkedList<BasicNameValuePair>();params.add(new BasicNameValuePair("param1", "Post方法"));params.add(new BasicNameValuePair("param2", "第二个参数"));try { HttpPost postMethod = new HttpPost(baseUrl); postMethod.setEntity(new UrlEncodedFormEntity(params, "utf-8")); //将参数填入POST Entity中 HttpResponse response = httpClient.execute(postMethod); //执行POST方法 Log.i(TAG, "resCode = " + response.getStatusLine().getStatusCode()); //获取响应码 Log.i(TAG, "result = " + EntityUtils.toString(response.getEntity(), "utf-8")); //获取响应内容} catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace();} catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace();} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();}
HttpClient传递复杂的参数,比如文件 需要额外的jar包
常见问题
异常处理 协议异常ClientProtocolException
: 无效的cookie 很多http请求需要提供登录凭证 如果没有则协议异常 连接超时SocketTimeoutException
: 无法连接到服务器比如服务器不可用 那么就连接超时 套接字超时ConnectTimeoutException
: 既定时间内未收到服务器响应此时可以连接到服务器 但是未收到响应 那么套接字超时
HttpConnectionparam.setconnectiontimeout(param,5000) //连接超时时间HttpConnectionparam.setsotimeout(param,5000) //套接字连接超时ConnManagerParams.settimeout(param,5000) //连接管理器的超时 定义应用程序等待多久才让一个连接退出连接池的管理 比如连接池已经满了 新的连接就必须要等待了
使用try catch块来捕获
多线程问题
可以设置单例的httpclient 这样就可以共享设置的连接参数,但是单例的话 多线程就会有问题
HttpClient httpClient = new DefaultHttpClient(); 有多线程问题
比如两个线程都调用httpClient.execute(getMethod); getMethod使用的是同一个HttpGet对象 那么毫无疑问多线程问题
HttpConnectionparam.setconnectiontimeout(params,5000)HttpConnectionparam.setsotimeout(params,5000)ConnManagerParams.settimeout(params,5000)HttpClient httpClient = new DefaultHttpClient(ThreadSafeClientManager conMgr,HttpParams params);
ThreadSafeClientManager
负责管理所有的httpclient的http连接 内部实现不会有多线程问题
此时的HttpParams作用在HttpClient上,所以可以供所有的HttpGet HttpPost对像共享
如果要定义自己的连接参数 那么可以
HttpGet getMethod = new HttpGet(baseUrl + "?" + param);HttpParams params= getMethod.getarams();HttpConnectionparam.setconnectiontimeout(param,5000);getMethod.setparams(params);
此时的HttpParams作用在HttpGet上,不会影响到HttpClient共享的连接参数
AndroidHttpClient
HttpClient子类 适用于android开发人员 连接超时/套接字超时默认20s
默认是线程安全的ThreadSafeClientManager
HttpUrlConnection
HttpUrlConnection属于Java的标准类库
更轻量了 推荐使用这个 4.4开始底层通过Okhttp来实现
HttpURLConnection的多线程问题? 因为采取Okhttp的底层实现,是木有多线程的问题的,具体是为什么,需要研究
HttpURLConnection使用
1. HttpURLConnection连接URL
1)创建一个URL对象
URL url = new URL(http://www.baidu.com);
2)利用HttpURLConnection对象从网络中获取网页数据
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
3)设置连接超时
conn.setConnectTimeout(6*1000);
4)对响应码进行判断
if (conn.getResponseCode() != 200) //从Internet获取网页,发送请求,将网页以流的形式读回来
throw new RuntimeException(“请求url失败”);
5)得到网络返回的输入流
InputStream is = conn.getInputStream();
6)String result = readData(is, “GBK”); //文件流输入出文件用outStream.write
7)conn.disconnect();
总结:
- 记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作.
- 返回的响应码200,是成功.
- 在Android中对文件流的操作和JAVA SE上面是一样的.
- 在对大文件的操作时,要将文件写到SDCard上面,不要直接写到手机内存上.
- 操作大文件是,要一遍从网络上读,一遍要往SDCard上面写,减少手机内存的使用.
- 对文件流操作完,要记得及时关闭.
2. 向Internet发送请求参数
步骤:
1)创建URL对象:URL realUrl = new URL(requestUrl);
2)通过HttpURLConnection对象,向网络地址发送请求
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
3)设置容许输出:conn.setDoOutput(true);
4)设置不使用缓存:conn.setUseCaches(false);
5)设置使用POST的方式发送:conn.setRequestMethod(“POST”);
6)设置维持长连接:conn.setRequestProperty(“Connection”, “Keep-Alive”);
7)设置文件字符集:conn.setRequestProperty(“Charset”, “UTF-8”);
8)设置文件长度:conn.setRequestProperty(“Content-Length”, String.valueOf(data.length));
9)设置文件类型:conn.setRequestProperty(“Content-Type”,”application/x-www-form-urlencoded”);
10)以流的方式输出.
总结:
- 发送POST请求必须设置允许输出
- 不要使用缓存,容易出现问题.
- 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头.
3. 向Internet发送xml数据
XML格式是通信的标准语言,Android系统也可以通过发送XML文件传输数据.
1)将生成的XML文件写入到byte数组中,并设置为UTF-8:byte[] xmlbyte = xml.toString().getBytes(“UTF-8”);
2)创建URL对象,并指定地址和参数:URL url = new URL(http://localhost:8080/itcast/contanctmanage.do?method=readxml);
3)获得链接:HttpURLConnection conn = (HttpURLConnection) url.openConnection();
4)设置连接超时:conn.setConnectTimeout(6* 1000);
5)设置允许输出conn.setDoOutput(true);
6)设置不使用缓存:conn.setUseCaches(false);
7)设置以POST方式传输:conn.setRequestMethod(“POST”);
8)维持长连接:conn.setRequestProperty(“Connection”, “Keep-Alive”);
9)设置字符集:conn.setRequestProperty(“Charset”, “UTF-8”);
10)设置文件的总长度:conn.setRequestProperty(“Content-Length”, String.valueOf(xmlbyte.length));
11)设置文件类型:conn.setRequestProperty(“Content-Type”, “text/xml; charset=UTF-8”);
12)以文件流的方式发送xml数据:outStream.write(xmlbyte);
总结:
- 我们使用的是用HTML的方式传输文件,这个方式只能传输一般在5M一下的文件.
- 传输大文件不适合用HTML的方式,传输大文件我们要面向Socket编程.确保程序的稳定性
- 将地址和参数存到byte数组中:byte[] data = params.toString().getBytes();
HttpClient还是HttpUrlConnection
参考 Android访问网络,使用HttpURLConnection还是HttpClient?
在Android 2.2版本之前,HttpClient拥有较少的bug,因此使用它是最好的选择。
而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择。它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。对于新的应用程序应该更加偏向于使用HttpURLConnection,因为在以后的工作当中我们也会将更多的时间放在优化HttpURLConnection上面。
其实现在嘛,两者都不用,就用Okhttp
HttpUrlConnection现在的底层实现就是通过Okhttp
HttpURLConnection java的标准类(java.net),什么都没封装,用起来太原始,不方便
HttpClient Apache开源框架,提供对HTTP协议访问的封装,包括http的请求头,参数,内容体,响应等及多线程的应用。
HttpClient方便,但是封装了太多,也可能导致网络请求速度变慢,灵活度不够
HttpClient就是一个增强版的HttpURLConnection ,HttpURLConnection可以做的事情 HttpClient全部可以做;HttpURLConnection没有提供的有些功能,HttpClient也提供了
Volley中两者的使用
我们知道Volley中api<=9使用的是HttpClientStack,内部使用HttpClient。api>9使用的是HurlStack,内部使用HttpUrlConnection
先来看HttpClientStack,使用起来很简单
private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers) { for (String key : headers.keySet()) { httpRequest.setHeader(key, headers.get(key)); } } @Override public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError { HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders); addHeaders(httpRequest, additionalHeaders); //缓存中的头 addHeaders(httpRequest, request.getHeaders()); //request中的设置的头 onPrepareRequest(httpRequest); HttpParams httpParams = httpRequest.getParams(); int timeoutMs = request.getTimeoutMs(); // TODO: Reevaluate this connection timeout based on more wide-scale // data collection and possibly different for wifi vs. 3G. HttpConnectionParams.setConnectionTimeout(httpParams, 5000); HttpConnectionParams.setSoTimeout(httpParams, timeoutMs); return mClient.execute(httpRequest); //调用HttpClient的excute方法,执行网络请求,最后直接返回HttpResponse } static HttpUriRequest createHttpRequest(Request<?> request, Map<String, String> additionalHeaders) throws AuthFailureError { case Method.GET: return new HttpGet(request.getUrl()); case Method.POST: { HttpPost postRequest = new HttpPost(request.getUrl()); postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); setEntityIfNonEmptyBody(postRequest, request); //设置post请求参数 return postRequest; ........ } default: throw new IllegalStateException("Unknown request method."); } private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest, Request<?> request) throws AuthFailureError { byte[] body = request.getBody(); if (body != null) { HttpEntity entity = new ByteArrayEntity(body); httpRequest.setEntity(entity); //setEntity方法设置post请求参数 } }
看吧,使用起来很方便简单,都是直接封装好了,,,下面来看HurlStack,使用起来就更负责了
@Override public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError { String url = request.getUrl(); HashMap<String, String> map = new HashMap<String, String>(); map.putAll(request.getHeaders()); //取出request设置的head map.putAll(additionalHeaders); //取出缓存中的Header,如果该request前面发起过网络请求,那么就会缓存下来,同时会把http的head也缓存 ........ URL parsedUrl = new URL(url); HttpURLConnection connection = openConnection(parsedUrl, request); //初始化HttpURLConnection对象 for (String headerName : map.keySet()) { connection.addRequestProperty(headerName, map.get(headerName)); //设置Http请求的head } setConnectionParametersForRequest(connection, request); // Initialize HttpResponse with data from the HttpURLConnection. ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); int responseCode = connection.getResponseCode(); if (responseCode == -1) { // -1 is returned by getResponseCode() if the response code could not be retrieved. // Signal to the caller that something was wrong with the connection. throw new IOException("Could not retrieve response code from HttpUrlConnection."); } StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(), connection.getResponseMessage()); BasicHttpResponse response = new BasicHttpResponse(responseStatus); //HttpResponse需要自己创建 if (hasResponseBody(request.getMethod(), responseStatus.getStatusCode())) { response.setEntity(entityFromConnection(connection)); //调用HttpResponse的setEntity方法设置相应内容 } for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) { if (header.getKey() != null) { Header h = new BasicHeader(header.getKey(), header.getValue().get(0)); response.addHeader(h); //调用HttpResponse的addHeader方法添加响应头 } } return response; } private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException { HttpURLConnection connection = createConnection(url); int timeoutMs = request.getTimeoutMs(); connection.setConnectTimeout(timeoutMs); //设置连接超时时间 connection.setReadTimeout(timeoutMs); connection.setUseCaches(false); //不使用缓存? connection.setDoInput(true); //允许输出 // use caller-provided custom SslSocketFactory, if any, for HTTPS if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) { ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory); } return connection; } //可以看到volley支持get,post,PUT等都支持的,符合http规范 static void setConnectionParametersForRequest(HttpURLConnection connection, Request<?> request) throws IOException, AuthFailureError { switch (request.getMethod()) { case Method.GET: // Not necessary to set the request method because connection defaults to GET but // being explicit here. connection.setRequestMethod("GET"); break; case Method.POST: connection.setRequestMethod("POST"); addBodyIfExists(connection, request); ........... } } private static void addBodyIfExists(HttpURLConnection connection, Request<?> request) throws IOException, AuthFailureError { byte[] body = request.getBody(); if (body != null) { connection.setDoOutput(true); connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType()); //request的getBodyContentType()方法可以设置Content-Type请求头 DataOutputStream out = new DataOutputStream(connection.getOutputStream()); out.write(body); //把getBody()返回的byte[]数组写入输入流, out.close(); } } private static HttpEntity entityFromConnection(HttpURLConnection connection) { BasicHttpEntity entity = new BasicHttpEntity(); InputStream inputStream; try { inputStream = connection.getInputStream(); } catch (IOException ioe) { inputStream = connection.getErrorStream(); } entity.setContent(inputStream); //把响应内容写入HttpEntity entity.setContentLength(connection.getContentLength()); entity.setContentEncoding(connection.getContentEncoding()); entity.setContentType(connection.getContentType()); return entity; }
看到两者的区别了吧?
HttpClient使用起来很简单
- mClient.execute(httpRequest); 直接返回HttpResponse对象,这个对象封装了响应内容和响应头
- httpRequest.setHeader(key, headers.get(key)); 给请求添加头
- HttpEntity entity = new ByteArrayEntity(request.getBody()); httpRequest.setEntity(entity); //给请求添加post参数
HttpURLConnection使用麻烦多了
HttpResponse对象需要自己创建,并手动添加响应内容和响应头,这里创建的是BasicHttpResponse实现了HttpResponse接口
- connection.addRequestProperty(headerName, map.get(headerName)); //设置Http请求的head
- DataOutputStream out = new DataOutputStream(connection.getOutputStream()); out.write(request.getBody()); //给请求添加post参数
- response.addHeader(h); //调用HttpResponse的addHeader方法添加响应头
- response.setEntity(entityFromConnection(connection)); //调用HttpResponse的setEntity方法设置相应内容
- Android HttpClient HttpUrlConnection用法总结
- HttpClient和HttpURLConnection用法
- android httpclient httpurlconnection
- 转载:Android HttpClient & HttpUrlconnection
- HttpURLConnection和HttpClient的用法
- Android HttpClient HttpUrlConnection上传文件
- Android网络HttpURLConnection和HttpClient
- Android学习 HttpClient 与 HttpUrlConnection
- android HttpURLConnection ,HttpClient设置Cookie
- Android--HttpURLConnection及HttpClient选择
- HttpURLConnection 与 Android HttpClient 对比
- Android HttpURLConnection及HttpClient选择
- Android网络HttpURLConnection和HttpClient
- Android HttpURLConnection及HttpClient选择
- Android之HttpClient和HttpUrlConnection
- Android HttpURLConnection用法详解
- Android HttpURLConnection的用法
- android HttpURLConnection用法详解
- scrollview and scrollbar
- FFMPEG视音频编解码
- vim学习笔记
- 【Android游戏开发十九】(必看篇)SurfaceView运行机制详解—剖析Back与Home按键及切入后台等异常处理!
- 中国移动咪咕属地化2016校招面经
- Android HttpClient HttpUrlConnection用法总结
- PHP页面跳转报错
- 安卓反编译:推荐一个最新反编译功能的工具
- 利用github-pages建立个人博客
- Fragment生命周期
- mvc
- Web Service概述
- 【Android游戏开发二十】物理游戏之重力系统开发,让你的游戏变得有质有量!
- HTTP请求和响应格式详细解析(转载)