《WCF技术内幕》翻译26:第2部分_第5章_消息:Buffered vs Streamed、序列化和反序列化消息

简介:

Buffered vs. Streamed消息

当我们在终结点之间流动的消息时,我们会本能地想到缓存。 换个方式来说,我们假设程序接收到一个Message 时,它已经知道整个Message 。这种方式称作缓存模式 (buffering)。与之相对的就是流处理模式( streaming),并且有2种流处理模式(streaming)。第一种是推模型(push model),发送者按照自己的节奏推送字节流到接收者。当流数据发送的时候,发送者把数据写到本地缓存直到写满为止,数据会发生给接收者,接收者会从本地缓冲区读取数据。第二种机制成为拉模型(pull model)。当流数据发送的时候,接收者从发送者请求数据,在收到请求以后,发送者发送请求的数据。这个过程会重复执行知道请求的数据发送完毕。WCF基础结构实现了第二种流处理方法。
在WCF里,Message的消息头块通常是缓存起来的,消息内容可以buffered或者streamed模式。缓存区的大小默认是64KB.(你会在第8章里了解如何改变这个设置。)如果消息体是streamed模式,它的大小就是无限制的。实际上,这意味着我们可以在WCF里传递流媒体。不是所有的消息都是流处理消息体元素。例如,小的消息就不需要streamed模式;缓存模式会更加高效地处理它们。更确切地说,一个大的消息本质上验证是十分困难的。想一下,一个例子,假如使用streamed模式发送一个30分钟长的电影作为消息体的消息。电影非常不错,并且可以在接收完毕前就可以播放给观众。如果数据流终止,并且没任何发送结束标记,处理错误就变得不太可能了,因为用户可能已经看到数据了,同样地,如果一个程序已经对数据做了数据签名,这个签名只能在整个数据流结构和缓存以后才能验证了,这就不适合使用streamed模式处理消息体数据。

序列化消息

既然你已经学习了如何创建消息,现在我们来研究一下如何序列化消息的全部或者某一部分。首先,Message类型上的所有序列化方法名称都是以 Write开始,而且这些方法都接受XmlWriter或者XmlDictionaryWriter类型的参数。消息的实际序列化工作由 XmlWriter或者XmlDictionaryWriter对象完成,而不是直接由 Message对象完成。记得前面关于XmlDictionaryWriter的讨论,实际的序列化包括消息序列化和编码2个步骤。序列化小的方法原型如下:
public void WriteStartEnvelope(XmlDictionaryWriter writer); 
public void WriteStartBody(XmlDictionaryWriter writer); 
public void WriteStartBody(XmlWriter writer); 
public void WriteBody(XmlDictionaryWriter writer); 
public void WriteBody(XmlWriter writer); 
public void WriteBodyContents(XmlDictionaryWriter writer); 
public void WriteMessage(XmlDictionaryWriter writer); 
public void WriteMessage(XmlWriter writer);
WriteMessage方法序列化消息的全部内容到 XmlWriter或者XmlDictionaryWriter包装的 Stream里。因为这些方法序列化整个消息,因此与其它方法相比,它们的使用频率最高。
Message类型同样定义了对于消息序列化进行粒度控制的方法。例如, WriteBody方法序列化body标签和元素到XmlWriter或者XmlDictionaryWriter包装的 Stream里。WriteBodyContents方法,话句话说,序列化body元素(没有body标签)到XmlDictionaryWriter包装的 Stream里。WriteStartEvelope方法简单的写<s:Envelope标签到到XmlDictionaryWriter包装的 Stream里。在WriteStartEnvelope之后立即调用WriteStartBody方法,会写XML namespace到envelope,并且序列化body开始标签,从序列化内容完全忽略消息头。实际上,如果我们需要在使用这些方法的时候对消息序列化做额外的控制,我们肯定想序列化消息头的内容。这个功能隐含在Message对象模型里,并且会在本章后面的“Message Headers类型”一节里做相应的介绍。记住,如果你想手工序列化一个消息,你必须明确序列化消息头块。还没有明确的方法可以写envelope或body的结束标签。但是,为了写envelope或body的结束标签,我们直接调用XmlWriter.  WriteEndElement方法。

反序列化消息

在接受程序里普遍存在的一个任务就是消息的反序列化。消息的反序列化是从一个序列化的消息创建一个新的消息的别称。因为我们已经过了如何创建一个Message对象,同样也讲了大部分的消息反序列化的内容。更确切地说,我们已经学习了如何使用 XmlDictionaryReader类型从一个Stream或者Byte创建一个Message。
想一下我们关于Message工厂方法的讨论,其中一种创建消息体的方法就是传递 Object给工厂方法。同样的方式,我们或许需要从一个Message实例反序列化Object。为了这个目的,Message类型定义了从Message对象反序列化消息体的成员。这些方法的原型如下;
 
public T GetBody<T>();
public T GetBody<T>(XmlObjectSerializer serializer);
泛型方法 GetBody允许调用者反序列化消息体的内容到T类型的对象里。另外一个方法接受一个XmlObjectSerializer参数,因此为消息体的反序列化提供了扩展点。不论我们调用哪个方法,我们必须知道Message的消息体内包含的类型信息。如果我们泛型方法里使用的类型和消息体的类型不兼容,就会抛出一个SerializationException异常。

检查Message 是否是SOAP Fault

正如你看到的,Message类型的实例表示一个SOAP 消息或者SOAP Fault。当接受程序反序列化一个Message的时候,它必须能够确定这个 Message是否是一个SOAP Fault,因为通常SOAP 消息和SOAP Fault的执行路径不同。因此,Message定义了一个只读属性 IsFault。简而言之,一旦一个Message对象从进来的Stream or  Byte反序列化完毕, IsFault属性会标记Message是否是一个SOAP Fault,这也是WCF基础结构对于反序列化的消息作出的第一次检查。我们可以通过改变前面代码里CreateAndShowMessage方法来演示这个属性的功能,如下所示;
 
private static void CreateAndShowMessage(MessageFault messageFault,
                                                                                 MessageVersion version) {
Message message = Message.CreateMessage(version,
                                                                                    messageFault,
                                                                                    "urn:SomeFaultAction");
// commented out for clarity
// Console.WriteLine("{0}\n", message.ToString());
    
// ** New code begins here **
MemoryStream stream = new MemoryStream();
// write the Message to a Stream
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(
            stream,null, null, false);
message.WriteMessage(writer);
writer.Flush();
    
stream.Position = 0;
    
// read the Message from the Stream从Stream读取消息
XmlDictionaryReader reader =
            XmlDictionaryReader.CreateBinaryReader(stream, new
                XmlDictionaryReaderQuotas());
message = Message.CreateMessage(reader, Int32.MaxValue, version);
    
// check if it is a Fault检查消息是否是SOAP Fault
Console.WriteLine("the message {0} a SOAP Fault",
            message.IsFault ? "is" : "is not");
}
当这些代码执行的时候(像前面的代码),产生下面的输出:
 
the message is a SOAP Fault
the message is a SOAP Fault
注意到对于连个创建对象Message.IsFault属性都返回 true,这里着重指出的是对于所有的表示SOAP Fault的Message对象, Message.IsFault属性都返回true,不管消息数据的编码和版本是什么。


 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/318585 ,如需转载请自行联系原作者


相关文章
|
21天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
1月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
2月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
2月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。
|
1月前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
31 0
|
3月前
|
JSON fastjson Java
niubility!即使JavaBean没有默认无参构造器,fastjson也可以反序列化。- - - - 阿里Fastjson反序列化源码分析
本文详细分析了 Fastjson 反序列化对象的源码(版本 fastjson-1.2.60),揭示了即使 JavaBean 沲有默认无参构造器,Fastjson 仍能正常反序列化的技术内幕。文章通过案例展示了 Fastjson 在不同构造器情况下的行为,并深入探讨了 `ParserConfig#getDeserializer` 方法的核心逻辑。此外,还介绍了 ASM 字节码技术的应用及其在反序列化过程中的角色。
83 10
|
3月前
|
存储 XML JSON
用示例说明序列化和反序列化
用示例说明序列化和反序列化
|
3月前
|
存储 Java 开发者
Java编程中的对象序列化与反序列化
【9月更文挑战第20天】在本文中,我们将探索Java编程中的一个核心概念——对象序列化与反序列化。通过简单易懂的语言和直观的代码示例,你将学会如何将对象状态保存为字节流,以及如何从字节流恢复对象状态。这不仅有助于理解Java中的I/O机制,还能提升你的数据持久化能力。准备好让你的Java技能更上一层楼了吗?让我们开始吧!
|
3月前
|
JSON 安全 编译器
扩展类实例的序列化和反序列化
扩展类实例的序列化和反序列化
37 1
|
3月前
|
XML Dubbo Java
分布式-序列化,反序列化
分布式-序列化,反序列化