HttpClient 翻译,详解Android架构进阶面试题

Set-Cookie:c2=b; path=“/”, c3=c; domain=“localhost”

2

获取所有头的最高效的方法是使用HeaderIterator接口

HttpResponseresponse = new BasicHttpResponse(HttpVersion.HTTP_1_1,

HttpStatus.SC_OK,“OK”);

response.addHeader(“Set-Cookie”,

“c1=a;path=/; domain=localhost”);

response.addHeader(“Set-Cookie”,

“c2=b;path=\”/\“, c3=c; domain=\“localhost\””);

HeaderIteratorit = response.headerIterator(“Set-Cookie”);

while(it.hasNext()) {

System.out.println(it.next());

}

输出>

Set-Cookie:c1=a; path=/; domain=localhost

Set-Cookie:c2=b; path=“/”, c3=c; domain=“localhost”

这是也是一个用于个别头元素上解释HTTP消息的便利方法。

HttpResponseresponse = new BasicHttpResponse(HttpVersion.HTTP_1_1,

HttpStatus.SC_OK,“OK”);

response.addHeader(“Set-Cookie”,

“c1=a;path=/; domain=localhost”);

response.addHeader(“Set-Cookie”,

“c2=b;path=\”/\“, c3=c; domain=\“localhost\””);

HeaderElementIteratorit = new BasicHeaderElementIterator(

response.headerIterator(“Set-Cookie”));

while(it.hasNext()) {

HeaderElementelem = it.nextElement();

System.out.println(elem.getName()+ " = " + elem.getValue());

NameValuePair[]params = elem.getParameters();

for(int i = 0; i < params.length; i++) {

System.out.println(“” + params[i]);

}

}

1.1.4HTTP实体

HTTP消息可以携带一个与请求或应答关联的内容实体。实体可被选择性地包含在请求和应答里。“请求”是用实体提交上去的,同时实体会附上请求。HTTP规格定义了两种附上实体的请求方法:POST和PUT。“应答”通常会被希望附上一个内容实体。这是一些异常应答:HEADmethod和204No Content,304 Not Modified,205Reset Content应答.

streamed**(流)**:是指一个stream里收到内容,或在飞速写入时产生。它包含了实体的类型,可从HTTP应答里接收到。streamed实体通常是不能重复的。

self-contained**(自控制)****😗*内容在内存里或可从连接或其他实体里获得。self-contained通常是可重复的。这种实体类型被广泛用在“HTTP请求附上实体”里。

wrapping**(交换)****😗*内容从另一个实体获得。

对于连接管理来说区分HTTP应答输出流的内容十分重要。对于由应用创建并用HttpClient发送的请求实体,streamed和self-contained间的区分一点也不重要。建议考虑使用不可重复的实体如streamed,那些可重复的就用self-contained。

*译者:这段翻译不太好,看不懂没关系,请继续往下看。

1.1.4.1可重复的实体

一个实体可以repeatable(重复使用)意味着它的内容可以读取多次。这只有selfcontained实体才能做到(如ByteArrayEntity或者StringEntity)。

1.1.4.2使用HTTP实体

实体可以代理二进制和字符内容,支持字符编码(tosupport the latter, ie. character content)。

以下情况都会创建一个实体:

1)执行一个被附上内容的请求;

2)请求成功同时将应答文本发送回客户端。

从实体读取内容有2种方法:

1)使用HttpEntity#getContent()方法来检索输入流,返回java.io.InputStream。

2)为HttpEntity#writeTo(OutputStream)方法提供一个输出流,当所有内容被写入指定的流后才会返回一次。

当实体随着一个输入消息被接收到,HttpEntity#getContentType()和HttpEntity#getContentLength()这两个方法可以用来读公共的元数据如:Content-Type头和Content-Length头(如何它们可获得)。Content-Type头可以为文本类型(如text/plain或text/html)包含字符编码,而HttpEntity#getContentEncoding()方法是用来读取这个信息的。如果头不能使用,将返回-1长度,同时内容类型为NULL。如果Content-Type头可获得,将返回头对象。

当创建一个输出消息时,元数据必需由实体创造者提供。

StringEntitymyEntity = new StringEntity(“important message”,

ContentType.create(“text/plain”,“UTF-8”));

System.out.println(myEntity.getContentType());

System.out.println(myEntity.getContentLength());

System.out.println(EntityUtils.toString(myEntity));

System.out.println(EntityUtils.toByteArray(myEntity).length);

输出>

Content-Type:text/plain; charset=utf-8

17

importantmessage

17

1.1.5保证释放底层资源

为了确保系统资源的正确释放,必需要至少关闭以下两种情况的其中之一:

1)与实体关联的内容流;

2)自身的应答。

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpGethttpget = new HttpGet(“http://localhost/”);

CloseableHttpResponseresponse = httpclient.execute(httpget);

try{

HttpEntityentity = response.getEntity();

if(entity != null) {

InputStreaminstream = entity.getContent();

try{

//do something useful

}finally {

instream.close();

}

}

}finally {

response.close();

}

关闭stream和关闭response的区别是,是否框架会由于消耗实体内容尝试保持底层连接,而后者会立即关闭和丢弃连接。

请注意HttpEntity#writeTo(OutputStream)方法也需要保证实体被完全写出后能正确地释放系统资源。如果这个方法是通过调用HttpEntity#getContent()来获得java.io.InputStream实例的,最后也是要关闭的。

使用流实体时,可以使用EntityUtils#consume(HttpEntity)方法来保证实体内容已被完全消耗和底层流被关闭。

这是一种情况,不管怎么样,只有实体应答的一小部分连接需要恢复和损失性能为了消耗剩下连接和制造连接可复用性的代价是非常高的,在这种情况下可以通过关闭应答来结束内容流。

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpGethttpget = new HttpGet(“http://localhost/”);

CloseableHttpResponseresponse = httpclient.execute(httpget);

try{

HttpEntityentity = response.getEntity();

if(entity != null) {

InputStreaminstream = entity.getContent();

intbyteOne = instream.read();

intbyteTwo = instream.read();

//Do not need the rest不需要等待

}

}finally {

response.close();

}

这个连接不能被重新使用,不过所有等级的资源会因为被正确分配而被保持。

1.1.6消费的实体连接

推荐使用HttpEntity#getContent()或HttpEntity#writeTo(OutputStream)方法来消费实体的内容。HttpClient也会伴随EntityUtils类发生,EntityUtils提供了几个能轻松在实体里读内容或信息的静态方法。你可以通过使用这个类的方法来将整个内容体恢复为string/ byte array(字符串或字节阵列)。然而,强烈反对使用EntityUtils,除非应答是来自可信的HTTP服务器和在限制长度内的答应。

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpGethttpget = new HttpGet(“http://localhost/”);

CloseableHttpResponseresponse = httpclient.execute(httpget);

try{

HttpEntityentity = response.getEntity();

if(entity != null) {

longlen = entity.getContentLength();

if(len != -1 && len < 2048) {

System.out.println(EntityUtils.toString(entity));

}else {

//Stream content out

}

}

}finally {

response.close();

}

在某些情况,可能会需要多次读实体。既然这样,实体内容必需要保存在内存或磁盘里。最简单的方法是使用BufferedHttpEntity类将源实体包装起来。这样就能从内存缓冲区里读源实体的内容了。在所有其它的实体包装方式里都会有一个源。

CloseableHttpResponseresponse = <…>

HttpEntityentity = response.getEntity();

if(entity != null) {

entity= new BufferedHttpEntity(entity);

}

1.1.7产生实体连接

HttpClient提供了几个类通过HTTP连接来高效输出’流’的内容。这些类的实例可以被实体联系上,并附上请求(如POST和PUT),从而为了在将实体内容附进输出的HTTP申请。HttpClient为大多数的普通数据容器如string,byte array, input stream, 和file:StringEntity,ByteArrayEntity,InputStreamEntity,和FileEntity提供了几个类。

Filefile = new File(“somefile.txt”);

FileEntityentity = new FileEntity(file,

ContentType.create(“text/plain”,“UTF-8”));

HttpPosthttppost = new HttpPost(“http://localhost/action.do”);

httppost.setEntity(entity);

请注意InputStreamEntity是不可反复使用的,它只能从底层数据流读取一次。通常推荐实例一个定制的HttpEntity类,使用self-contained来代替使用普通的InputStreamEntity.FileEntity。

1.1.7.1HTML框架

许多应用需要模拟HTML框架的过程,比如,为了从应用里登陆或提交输入数据。为帮助这个工作过程,HttpClient提供了实体类UrlEncodedFormEntity。

Listformparams = new ArrayList();

formparams.add(newBasicNameValuePair(“param1”, “value1”));

formparams.add(newBasicNameValuePair(“param2”, “value2”));

UrlEncodedFormEntityentity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);

HttpPosthttppost = new HttpPost(“http://localhost/handler.do”);

httppost.setEntity(entity);

UrlEncodedFormEntity实例使用这样调用URL编码方式来编码参数,并产生如下内容:

param1=value1&param2=value2

1.1.7.2内容分块

通常推荐让HttpClient选择最合适的基于HTTP消息特性的传输编码。这是可能的,然而,可以通过设置HttpEntity#setChunked()为true来通知HttpClient首先使用分块编码。请注意,HttpClient用这个flag仅作为一个暗示。当使用HTTP协议版本不支持块编码(如HTTP/1.0)时,这个值会被忽略。

StringEntityentity = new StringEntity(“important message”,

ContentType.create(“plain/text”,Consts.UTF_8));

entity.setChunked(true);

HttpPosthttppost = new HttpPost(“http://localhost/acrtion.do”);

httppost.setEntity(entity);

1.1.8应答操纵器

最简单和最方便的操纵应答方法是使用ResponseHandler接口,它包括handleResponse(HttpResponseresponse)方法。这个方法完全地解除了用户对连接管理的麻烦。当使用ResponseHandler时,HttpClient会自动地去关心保证资源释放(连接管理者不顾后果地连接返回不管是否请求成功或引起异常)。

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpGethttpget = new HttpGet(“http://localhost/json”);

ResponseHandlerrh = new ResponseHandler() {

@Override

publicJsonObject handleResponse(

finalHttpResponse response) throws IOException {

StatusLinestatusLine = response.getStatusLine();

HttpEntityentity = response.getEntity();

if(statusLine.getStatusCode() >= 300) {

thrownew HttpResponseException(

statusLine.getStatusCode(),

statusLine.getReasonPhrase());

}

if(entity == null) {

thrownew ClientProtocolException(“Response contains no content”);

}

Gsongson = new GsonBuilder().create();

ContentTypecontentType = ContentType.getOrDefault(entity);

Charsetcharset = contentType.getCharset();

Readerreader = new InputStreamReader(entity.getContent(), charset);

returngson.fromJson(reader, MyJsonObject.class);

}

};

MyJsonObjectmyjson = client.execute(httpget, rh);

1.2HttpClient接口


HttpClient接口为HTTP请求实行描绘了最基本了协议。它推行:

1)不受限制;

2)详细的请求执行过程;

3)指定连接管理员、正确的管理、鉴定和举起独特的执行情况。

这会将会更容易用额外的功能(如应答内容缓存)来装饰接口。

通常HttpClient执行情况担当许多特别意图处理器的外表或策略接口执行情况答应,为了对HTTP协议(如更改、鉴定处理、做关于连接持续连接决定和保持连接)的特别方面的进行处理。这能让使用者有选择性地替代那些定制的、应用程序明确的默认执行情况。

ConnectionKeepAliveStrategykeepAliveStrat = new DefaultConnectionKeepAliveStrategy() {

@Override

publiclong getKeepAliveDuration(

HttpResponseresponse,

HttpContextcontext) {

longkeepAlive = super.getKeepAliveDuration(response, context);

if(keepAlive == -1) {

//Keep connections alive 5 seconds if a keep-alive value

//has not be explicitly set by the server

keepAlive= 5000;

}

returnkeepAlive;

}

};

CloseableHttpClienthttpclient = HttpClients.custom()

.setKeepAliveStrategy(keepAliveStrat)

.build();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

总结

找工作是个很辛苦的事情,而且一般周期都比较长,有时候既看个人技术,也看运气。第一次找工作,最后的结果虽然不尽如人意,不过收获远比offer大。接下来就是针对自己的不足,好好努力了。

最后为了节约大家的时间,我把我学习所用的资料和面试遇到的问题和答案都整理成了PDF文档,都可以分享给有需要的朋友,如有需要私信我【资料】或者**【点这里】免费领取**

《Android面试复习资料汇总》

喜欢文章的话请关注、点赞、转发 谢谢!

m()

.setKeepAliveStrategy(keepAliveStrat)

.build();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Xu4lMvPp-1710662846289)]
[外链图片转存中…(img-5wJM4gGH-1710662846289)]
[外链图片转存中…(img-GKKwek0F-1710662846290)]
[外链图片转存中…(img-G2WgBGqU-1710662846290)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-iHTSfgvh-1710662846290)]

总结

找工作是个很辛苦的事情,而且一般周期都比较长,有时候既看个人技术,也看运气。第一次找工作,最后的结果虽然不尽如人意,不过收获远比offer大。接下来就是针对自己的不足,好好努力了。

最后为了节约大家的时间,我把我学习所用的资料和面试遇到的问题和答案都整理成了PDF文档,都可以分享给有需要的朋友,如有需要私信我【资料】或者**【点这里】免费领取**

《Android面试复习资料汇总》

喜欢文章的话请关注、点赞、转发 谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值