续(一)
1.1.3. HTTP实体
HTTP消息能够携带于请求和响应有关系的内容实体。实体可以在一些请求和一些响应中找到,因为它们是可选的。使用实体的请求被称作封闭实体请求。HTTP规范定义了两个封闭实体方法:POST和PUT。响应通常都会被期望附加一个内容实体。但这个规则也有例外,例如响应HEAD方法和204 No Content、304 Not Modified、205 Reset Content响应。
HttpCore根据内容的来源将实体分为三种不同的种类:
* 流式:实体接收自一个流或动态产生的。特别的,此类中的实体是从一个连接接收的。流式实体通常是不可重复的。
* 自包含式:内容是在内存中或捕获的,这意味着它独立于一个连接或其它实体。自包含式实体通常是可重复的。
* 包装式:内容捕获自另外一个实体。
1.1.3.1. 可重复实体
一个实体能被重复,意思是它的内容能够被不止一次地读取。这仅对自包含式实体是可能的(像ByteArrayEntity或StringEntity)。
1.1.3.2. 使用HTTP实体
因为一个实体既能表达二进制,也能表达字符内容,所以它是支持字符编码的(去支持后者,例如字符内容)。当执行一个附加内容的请求或请求成功并且响应体被用于作为结果发送给客户端时实体就会被创建。
要从实体中读取内容,一个是通过HttpEntity#getContent()方法获取一个输入流;一个是给HttpEntity#writeTo(OutputStream)方法提供一个输出流。一旦所有的内容都写入给定的输出流中后该方法就会返回。请注意一些非流(自包含)形式的实体可能无法有效地把它们的内容表现为一个java.io.InputStream。对于这样的实体来说只实现HttpEntity#writeTo(OutputStream)方法才是合法的并且从HttpEntity#getConten()方法中抛出UnsupportedOperationException。
EntityUtil类提供一些静态方法来简化从实体中提取内容或信息。取代直接读取java.io.InputStream,通过使用源自本类的方法,可以捕获完整的内容到一个字符串或二进制数组中。
当实体随着到埠消息被接受后,HttpEntity#getContentType()方法和HttpEntity#getContentLength()方法就可以用来读取诸如Content-Type头和Content-Length头这样的元数据了(如果他们可用的话)。因为Content-Type头是可以为像text/plain或text/html这样的文本mime类型包含一个字符编码的,所以HttpEntity#getContentEncoding()方法就被用于读取这个信息。如果头不可用,将会返回-1,content类型是NULL。如果content-type头可用,将会返回一个Header对象。
当为出埠消息创建一个实体时,实体创建者要提供元数据。
*****************************************************************
* *
* StringEntity myEntity = new StringEntity("important message", *
* Consts.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); *
* *
*****************************************************************
stdout>
*******************************************
* *
* Content-Type: text/plain; charset=UTF-8 *
* 17 *
* important message *
* 17 *
* *
*******************************************
1.1.3.3. 确保释放系统资源
为了确保完全地释放系统资源就一定要关闭与实体有关的内容流。
***************************************************
* *
* HttpResponse response; *
* HttpEntity entity = response.getEntity(); *
* if (entity != null) { *
* InputStream instream = entity.getContent(); *
* try { *
* // do something useful *
* } finall *
* } *
* *
***************************************************
当与流式实体工作时,可以使用EntityUtil#consume(HttpEntity)方法去确保实体内容被完全消耗和底层流被关闭。
1.1.4. 创建实体
这里有若干个创建实体的方法。HttpCore提供了如下一些实现:
* BasicHttpEntity
* ByteArrayEntity
* StringEntity
* InputStreamEntity
* FileEntity
* EntityTemplate
* HttpEntityWrapper
* BufferedHttpEntity
1.1.4.1. BasicHttpEntity
顾名思义,这个基本实体描述一个底层流。一般的,使用这个类从HTTP消息中接收实体。
这个实体有一个空构造器。构造之后,它描述了一个没有内容的,并且内容长度值为负数的实体。
需要设置内容流,和可选长度。这分别可以用BasicHttpEntity#setContent(InputStream)和BasicHttpEntity#setContentLength(long)方法来完成。
*************************************************************
* *
* BasicHttpEntity myEntity = new BasicHttpEntity(); *
* myEntity.setContent(someInputStream); *
* myEntity.setContentLength(340); // sets the length to 340 *
* *
*************************************************************
1.1.4.2. ByteArrayEntity
ByteArrayEntity是一个自包含的、从给定的字节数组中获取内容的可重复实体。提供一个字节数组给构造器。
**********************************************************************
* *
* ByteArrayEntity myEntity = new ByteArrayEntity(new byte[] {1,2,3}, *
* ContentType.APPLICATION_OCTET_STREAM); *
* *
**********************************************************************
1.1.4.3. StringEntity
StringEntity是一个自包含的、从一个java.lang.String对象中获取内容的可重复实体。它有三个构造器,有一个给定java.lang.String对象的简单构造器;第二个另需带有字符串中的数据的字符编码;第三个允许指定mime类型。
************************************************************************************
* *
* StringBuilder sb = new StringBuilder(); *
* Map env = System.getenv(); *
* for (Map.Entry envEntry : env.entrySet()) { *
* sb.append(envEntry.getKey()) *
* .append(": ").append(envEntry.getValue()) *
* .append("\r\n"); *
* } *
* // construct without a character encoding (defaults to ISO-8859-1) *
* HttpEntity myEntity1 = new StringEntity(sb.toString()); *
* // alternatively construct with an encoding (mime type defaults to "text/plain") *
* HttpEntity myEntity2 = new StringEntity(sb.toString(), Consts.UTF_8); *
* // alternatively construct with an encoding and a mime type *
* HttpEntity myEntity3 = new StringEntity(sb.toString(), *
* ContentType.create("text/plain", Consts.UTF_8)); *
* *
************************************************************************************
1.1.4.4. InputStreamEntity
InputStreamEntity是一个流式的,从一个输入流中获取内容的不可重复实体。提供输入流和内容长度来构造它。使用内容长度值来限制从java.io.InputStream中读取数据的总数。如果长度匹配输入流中的可用内容长度,那么届时所有的数据都将会被发送。另外,一个负的内容长度值将从数据流中读取所有的数据,这与提供精确内容长度是一样的,所以使用长度值去限制数据读取量。
*********************************************************************
* *
* InputStream instream = getSomeInputStream(); *
* InputStreamEntity myEntity = new InputStreamEntity(instream, 16); *
* *
*********************************************************************
1.1.4.5. FileEntity
FileEntity是一个自包含式的,从一个文件中捕获内容的可重复实体。这种实体通常用在流化不同类型的大文件,那些你要提供文件内容类型的地方。例如,发送一个zip文件时需要提供内容类型为:application/zip,而对于XML则是:application/xml。
**********************************************************
* *
* HttpEntity entity = new FileEntity(staticFile, *
* ContentType.create("application/java-archive")); *
* *
**********************************************************
1.1.4.6. HttpEntityWrapper
这是创建包装实体的基类,包装实体持有一个到一个被包装的实体的引用并且代理了所有的到它的函数调用。包装实体的实现能衍生于这个类并且只需要覆盖那些不应该被代理到包装实体的方法。
1.1.4.7. BufferedHttpEntity
BufferedHttpEntity是HttpEntityWrapper的一个子类,需要提供另一个实体来构造它。它从这个提供的实体中读取内容。并缓存其在内存中。
这使得用一个不可重复实体制作一个可重复实体成为可能。如果提供的实体易经是可重复的了,那么将会简单地传递函数调用给下层的实体。
*****************************************************************
* *
* myNonRepeatableEntity.setContent(someInputStream); *
* BufferedHttpEntity myBufferedEntity = new BufferedHttpEntity( *
* myNonRepeatableEntity); *
* *
*****************************************************************
未完待续。。。
阅读(1915) | 评论(0) | 转发(0) |