随着时间的推移,已经形成这样一种惯例:即将应用程序构建成一组组件,分布于计算机网络之间,并作为整个程序的一部分一起运行。过去,分布式应用程序逻辑 需要具备组件/对象技术,例如,Microsoft? 分布式组件对象模型 (DCOM)、Object Management Group 的公共对象请求代理程序体系结构 (CORBA) 或 Sun 的远程方法调用 (RMI)。这些技术提供了可靠的、可升级的体系结构,以满足对应用程序日益增长的需要。
尽管这些基于组件的技术在 Intranet 环境中运行良好,但如果试图将其应用到 Internet 上,则会遇到两个大的问题。首先,这些技术不能进行交互操作。虽然这些技术都能处理对象,但在细节上却不尽相同。例如,生命周期管理、对构造函数的支持以 及对继承的支持程度。第二,更重要的是,它们都着眼于 RPC 形式的通信,这通常会围绕对象方法的显式调用而构建紧密耦合的系统。
相 反,基于浏览器的 Web 应用程序是松散耦合的,具有很强的互操作性。它们使用 HTTP 进行通信,交换许许多多不同格式的 MIME 类型数据。Web 服务使传统的 Web 编程模型适用于各种应用程序,而不仅仅是基于浏览器的应用程序。它们使用 HTTP 和其他 Internet 协议交换 SOAP 消息。由于 Web 服务依赖于 HTTP、XML、SOAP 和 WSDL 等行业标准,在 Internet 上展示应用程序的功能,因此它们独立于编程语言、平台和设备。
ASP.NET Web 服务基础结构通过将 SOAP 消息映射到方法调用,为 Web 服务提供了简单的 API。通过提供一种非常简单的编程模型(基于将 SOAP 消息交换映射到方法调用),它实现了此机制。ASP.NET Web 服务的客户端不需要了解用于创建它们的平台、对象模型或编程语言。而服务也不需要了解向它们发送消息的客户端。唯一的要求是:双方都要认可正在创建和使用 的 SOAP 消息的格式,该格式是由使用 WSDL 和 XML 架构 (XSD) 表示的 Web 服务合约定义来定义的。
.NET 框架支持两个截然不同的分布式编程模型 - Web 服务和分布式对象,这给开发人员造成了极大的混乱。系统何时应该使用 ASP.NET Web 服务,何时应该使用 .NET Remoting 呢?要回答这个问题,必须了解这两种技术的工作原理。
返回页首
序列化和元数据
所 有分布式通信管线最终都要做两件事:将程序数据类型实例封送为能够在网络上传递的消息,并且提供对消息样式的描述。前者是使用某种形式的序列化引擎(或称 为封送拆收器)完成的,后者是通过某种形式的元数据完成的。例如,对于大多数(现代的)DCOM 接口来说,序列化引擎是类型库封送拆收器,而类型库提供元数据。ASP.NET Web 服务和 .NET Remoting 之间的主要不同在于它们如何将数据序列化为消息,以及它们为元数据选择的格式。
ASP.NET Web 服务、XmlSerializer 和 XSD
ASP.NET Web 服务依赖于 System.Xml.Serialization.XmlSerializer 类,在运行时将数据封送到 SOAP 消息中以及从 SOAP 消息中封送数据。对于元数据,它们生成 WSDL 和 XSD 定义,说明消息中包含什么样的内容。完全依赖于 WSDL 和 XSD 使 ASP.NET Web 服务元数据具有可移植性;它表示数据结构的方法,对于不同平台上使用不同编程模型的其他 Web 服务工具包也可以理解。在某些情况下,这限制了可以从 Web 服务中提供的类型 - XmlSerializer 只能封送可以用 XSD 表示的数据。也就是说,XmlSerializer 将不能封送对象图形,而且对于容器类型的支持也很有限。
尽管这些限制从传统的分布式 对象的角度来看似乎很重要,但它们有助于确保与其他 Web 服务框架的互操作性 - 这是松散耦合的 Web 服务模型的基本目标。大量自定义属性使您能够注释数据类型,以控制 XmlSerializer 封送它们的方法,从而增强了对互操作性的支持。因此,您可以细致地控制在对象进行序列化时生成的 XML 的形状。另外,还可以对基于 ASP.NET 的 Web 服务进行调整,以便用文字 XSD 或 SOAP 编码规则(例如,SOAP 第 5 节)来描述消息。文字 XSD 是默认的,而且将成为以后的标准。它还包括 SOAP 编码支持,以便与现有的工具包进行互操作。这对用户很有帮助,特别是当用户需要与现有 Web 服务或客户端(它们需要使用预定义的消息格式进行通信)进行通信时更是如此。
public class Methods : MarshalByRefObject
{
// The Now method returns the current date and time
public string Now()
{
return System.DateTime.Now.ToString();
}
}
If you generate WSDL from this class, the binding information includes .NET Remoting-specific details, as shown below.
这 些额外的元素是合法的,因为 WSDL 规范支持可扩展性。任何运作良好的 Web 服务工具包如果不理解它们都会简单地忽略它们。但是,有些是 Web 服务工具包不能忽略的。例如,下面是一个返回 Microsoft? ADO.NET System.Data.DataSet 的 Remoting 端点。
public class Methods : MarshalByRefObject
{
public System.Data.DataSet GetEmptyDataSet()
{
return new System.Data.DataSet();
}
}
下面是为此方法的输出消息生成的 WSDL 定义:
通 常情况下,WSDL 消息指的是使用 XML 架构在特定的命名空间中定义的类型。但在这种情况下,用于 “数据集” 类型的命名空间的前缀 ns3 不是在 XSD 中定义的,而是通过运行时隐式定义的。本例中的前缀 ns3 应绑定到由以下 URI 确定的 XML 命名空间:
此 WSDL 定义的客户端要了解这个“众所周知”的 URI 的特殊意义 — 它是 .NET 框架中包括的特定运行时程序集的严格名称(由四部分组成)。这种 WSDL 对于使用 .NET Remoting 实现的客户端非常有用,因为它们可以使用适于封送的信息生成代理程序集。但是,对于不理解此 URI 并希望为 “数据集” 类型找到架构定义的其他 Web 服务工具包(包括 ASP.NET),这种 WSDL 将毫无用处。
问题依然没有解决:可以使用 .NET Remoting 建立 Web 服务吗?对,严格地说,可以。但是,不使用 .NET Remoting 管线的用户能够使用它们吗?回答是:也许可以,如果您小心地将端点减少到基本数据类型和语义。也就是说,如果您要与其他 Web 服务工具包进行互操作,则需要将参数限制到内置的简单类型和您自己的数据类型(不能使用 “数据集” 这样的 .NET 框架类型),而且要避免客户端激活的对象和事件。简而言之,如果您关心使用范围,则需要把自己限制到 ASP.NET Web 服务所支持的那些功能。
或者采取更好的方法,使用 ASP.NET Web 服务,因为这正是设计它们的目的所在。
返回页首
分布式应用程序设计:ASP.NET Web 服务和 .NET Remoting
ASP.NET Web 服务偏向于 XML Schema 类型系统,提供具有广泛使用范围的跨平台支持的简单编程模型。.NET Remoting 偏向于运行时类型系统,提供较为复杂而且使用范围小得多的编程模型。这种本质上的差别是决定使用哪种技术的主要因素。但是,还要考虑很多其他设计因素,包 括传输协议、主机进程、安全性、性能、状态管理以及对事务的支持等。
传输协议和主机进程
尽管 SOAP 规范并不要求用 HTTP 作为传输协议,但是客户端只能通过 HTTP 访问使用 ASP.NET Web 服务实现的 Web 服务,因为它是 ASP.NET 支持的唯一一种传输协议。服务是通过 IIS 调用的,并在 ASP.NET 的辅助进程 aspnet_wp.exe 中执行。
.NET Remoting 使您能够在任何类型的应用程序(包括 Windows 窗体、托管的 Windows 服务、控制台应用程序或 ASP.NET 辅助进程)中灵活地托管远程对象。正如前面所述,.NET Remoting 提供两个传输信道——TCP 和 HTTP。这两个信道都能使用套接字提供任意发送和接收进程之间的通信。
它还能将 HTTP 信道与 IIS 和 ASP.NET 辅助进程集成。这一点很重要,原因有以下几点。首先,它是当客户端请求到达时自动启动 .NET Remoting 端点的唯一方法。.NET Remoting 管线不包括启动远程服务器所需的 DCOM 类型的服务控制管理器 (SCM)。如果从任意进程中提供远程对象,则需要确保那些进程正在运行。还必须确保它们是线程安全的,例如,线程 A 不能在线程 B 开始关闭进程之后激活对象。如果从 ASP.NET 提供远程对象,则可以利用 Aspnet_wp.exe 辅助进程,这样既可自动启动又具有线程安全的优势。第二,与 IIS 集成是确保跨进程 .NET Remoting 调用的唯一途径,如下一节所述。
ASP.NET Web 服务和 .NET Remoting 基础结构都是可扩展的。您可以过滤入站和出站消息,从多方面控制类型封送和元数据的生成。使用 .NET Remoting,还能实现您自己的格式化程序和信道。
安全性
由 于 ASP.NET Web 服务依赖于 HTTP,因此它们与标准的 Internet 安全性基础结构相集成。ASP.NET 利用 IIS 的安全性功能,为标准 HTTP 验证方案(包括基本、简要、数字证书,甚至 Microsoft? .NET Passport)提供了强有力的支持。(还可以使用 Windows 集成验证,但只能用于信任域中的客户端。)使用可用的 HTTP 验证方案的一个优势在于,无需在 Web 服务中更改代码,IIS 是在 ASP.NET Web 服务被调用之前执行验证的。ASP.NET 还支持基于 .NET Passport 的验证和其他自定义的验证方案。ASP.NET 支持基于目标 URL 的访问控制,并通过与 .NET 代码访问安全性 (CAS) 基础结构的集成支持访问控制。SSL 可用于确保通信的安全。
尽管这些标准传输技术对于确保 Web 服务相当有效,但它们只能做到这种程度。在涉及到不同信任域中多个 Web 服务的复杂情况下,还得建立自定义的特殊解决方案。Microsoft 和其他公司正致力于创建一套安全性规范,该规范将基于 SOAP 消息的可扩展性提供消息级别的安全性功能。这些规范之一是 XML Web 服务安全性语言(WS-Security),它为消息级别的凭据传输、消息完整性和消息保密定义了框架。
正如上一节所述,一般情况 下,.NET Remoting 管线不能确保跨进程调用的安全。使用 ASP.NET 托管于 IIS 中的 .NET Remoting 端点可以利用 ASP.NET Web 服务可用的所有安全性功能,包括对使用 SSL 确保有线通信的安全性的支持。如果您正在使用托管在进程中的 TCP 信道或 HTTP 信道(而不是 aspnet_wp.exe),则必须自己执行身份验证、授权和保密机制。
另一个要关注的 安全性问题是,在不必更改默认安全性策略的情况下,从不完全信任的环境中执行代码的能力。ASP.NET Web 服务客户端代理可以在这些环境中工作,但 .NET Remoting 代理则不能。要从不完全信任的环境中使用 .NET Remoting 代理,需要特殊的序列化权限。默认情况下,该权限不会授予从 Intranet 或 Internet 上下载的代码。如果要在不完全信任的环境中使用 .NET Remoting 客户端,则需要更改从那些区域中加载的代码的默认安全性策略。当您从运行于沙箱(如下载的 Windows 窗体应用程序)中的客户端连接到系统时,ASP.NET Web 服务是较简单的选择,因为不需要更改安全性策略。
状态管理
默 认情况下,ASP.NET Web 服务模型采用无状态的服务结构;它并不是本能地与来自同一个用户的多个调用相关。另外,客户端每次调用 ASP.NET Web 服务时,都创建一个新的对象以服务于该请求。方法调用完成后,该对象即被破坏。要维护请求之间的状态,可以使用 ASP.NET 页面使用的相同技术(例如,Session 和 Application 属性包),也可以自己实现自定义的解决方案。
.NET Remoting 支持许多状态管理选项,并且可能与来自同一个用户的多个调用相关或不相关,这取决于您选择的对象生命周期架构。SingleCall 对象是无状态的(如用于调用 ASP.NET Web 服务的对象),Singleton 对象共享所有客户端的状态,客户端激活的对象在每个客户端的基础上保持状态(带有其产生的所有相关的可升级性和可靠性问题)。
性能
从 原始性能方面来讲,使用 TCP 信道和二进制格式化程序时,.NET Remoting 管线能够提供最快的通信。在我们进行的比较 ASP.NET Web 服务和 .NET Remoting 的相对性能的几乎所有的测试中,ASP.NET Web 服务在性能上都超出了使用 HTTP 或 TCP 信道的 SOAP 格式化程序的 .NET Remoting 端点。更有意思的是,使用二进制格式化程序和 HTTP 信道的 ASP.NET 和 .NET Remoting 端点在性能上非常相近。(更多信息,请参见 Performance Comparison:NET Remoting vs. ASP.NET Web Services。)
企业服务
ASP.NET Web 服务或通过 .NET Remoting 提供的对象可以使用本地事务根据单个数据库协调工作。如果需要根据多个资源协调工作,可以使用 .NET 企业服务(又称 COM+)公布的事务(由 COM+ 管线管理的 DTC 分布式事务)。但要注意的是,ASP.NET Web 服务和 .NET Remoting 管线都不能传播公布的事务,因此两种端点都不可能通过跨进程的调用继承公布的事务。
这不一定是件坏事。一般来讲,公布 的事务比本地事务代价要高,而要跨进程传播公布的事务,则代价会更高。如果确实需要这一功能,简单的解决方案是在 .NET 企业服务的服务器应用程序中部署一个从 System.EnterpriseServices.ServicedComponent 派生的类(更多信息,请参见 COM+ Integration:How .NET Enterprise Services Can Help You Build Distributed Applications)。对该类对象的跨进程调用将使用 DCOM 进行处理,以确保正确传播事务环境。较难的解决方案是使用底层的 API,手动传播分布的事务。
值得注意的是,传统的分布式事务模型一般 不适用于松散耦合的 Web 服务。基于补偿事务的模型(即,撤消其他事务所提交工作的事务)更有意义,因为其隔离约束条件并不是很严格。在包括 Microsoft 的 Web 服务供应商中有一种普遍的说法,即 Web 服务空间需要的事务模型越灵活,该空间中进行的工作越多。等到定义出 Web 服务事务的标准方法时,您就可以根据情况使用本地或公布的事务实现自己的补偿架构了。
这里写点抛砖引玉,希望大家能把自己整理的问题及解决方法晾出来,Mark一下,利人利己。
出现问题先搜一下文档上有没有,再看看度娘有没有,再看看论坛有没有。有报错要看日志。下面简单罗列下常见的问题,大多文档上都有提到的。
1、repeated column width is largerthan paper width:
这个看这段话应该是很好理解的。比如做的模板页面宽度只能放
这个问题我实在是为整个 springsource 的员工蒙羞
如果大家使用 spring 控制事务,使用 Open Session In View 模式,
com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.
简单模拟实现数据库连接池
实例1:
package com.bijian.thread;
public class DB {
//private static final int MAX_COUNT = 10;
private static final DB instance = new DB();
private int count = 0;
private i
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace WindowsFormsApplication1
{
Configuring Spring and JTA without full Java EE
http://spring.io/blog/2011/08/15/configuring-spring-and-jta-without-full-java-ee/
Spring doc -Transaction Management
http://docs.spring.io/spri