转Silverlight和Java的互操作
时间:2010-09-14 来源:永恒的记忆
本文针对那些希望把Silverlight集成到解决方案中的Java社区开发人员,给出了一些入门指导。微软Silverlight是一个跨浏览器、跨平台和跨设备的浏览器插件,旨在设计、开发和发布下一代多媒体体验与富交互(rich interface application)的网络应用程序。 本文同时也介绍了Silverlight的一些背景知识,其基本功能和开发理念;介绍了在开发支持多种媒体的富客户端应用时如何合理定位Silverlight;还介绍了Silverlight的架构,优点及其局限性等等。
本文探讨了Silverlight和Java交互的三种不同情况:SOAP web服务、REST web服务以及聚合(RSS)服务。SOAP web服务和REST web服务是通过NetBeans中的工具来实现的。文中为每种交互都提供了演示程序代码,并且讨论了最适合应用该种交互的情况。Silverlight也可以直接与sockets交互,但相对比较复杂,并不常见,因此将会在以后加以讨论。本文着重于Silverlight 2 Beta 2的Silverlight-Java交互的讨论和一些架构方面的指导。
范围
本文将主要讨论Silverlight-Java的互操作。通过Visual Studio创建一个Silverlight应用程序,帮助开发者对下列这些互操作方式有所了解:
- 与SOAP web服务的互操作
- 与REST服务的互操作
- 与聚合 (RSS) 服务的互操作
Silverlight也可以与sockets交互,但相对比较复杂,本文将不作讨论。
终极目标
- 为Java社区提供实现基本的Silverlight-Java服务互操作的几种可选方案。
目标
- 读者对什么是Silverlight及其用途有准确的理解。
- 读者对Silverlight的架构,它的优缺点,能有个基本的了解。
- 通过对上文“范围”一节中提到的三种基本互操作实例的描述,就Silverlight客户端是如何与Java服务进行交互这个问题给读者提供一个实用的指南。
Silverlight简介
微软Silverlight是个跨浏览器、跨平台、跨设备的浏览器插件,旨在设计、开发和发布下一代多媒体体验与富交互(rich interface application)的网络应用程序。Silverlight的定位是,应用于可以快速部署到浏览器中的富互联网应用。 “Silverlight是为连接到主机的网页内容而设计的,其特点是不但用户可深入地参与到交互中,而且应用还可在任何浏览器中运行。”使用Silverlight的场景。
把用户界面设计和底层逻辑分开可以大大提高应用程序开发生命周期(ADLC)的生产率。结合使用Microsoft Expression和Microsoft Visual Studio,用户界面设计人员和开发人员能够发挥各自所长,改进相互间的合作。
扩展应用程序标记语言(XAML)是一种基于XML的说明性语言,支持对流程的控制,专门用来做用户界面设计。而.NET语言则用来编写用户界面的后台逻辑,例如VB.NET、C#、IronRuby和IronPython。Windows Presentation Foundation (WPF)和Silverlight都采用XAML。
Silverlight的运行时环境是其架构的基础。Silverlight 2 Beta 2有一个一次性下载的大小为4.6MB的插件,能够部署到IE、Firefox、Opera或者Safari浏览器中。一个zip格式的“.xap”文件是Silverlight应用程序的开发包。这个“.xap”包中包含了应用程序及其接口,供Silverlight插件控制运行。这个“.xap”文件是在Visual Studio .NET中开发的,每次编译,客户端的“.xap”文件都会得到更新。Silverlight应用程序(“.xap”文件包)可以由任何web服务器部署。
图1:Web浏览器沙箱中的Silverlight
Silverlight控制器内嵌在HTML网页中,自然就包含在web浏览器的沙箱内。 MSDN有一篇技术文章Silverlight架构概述对Silverlight的架构做了大体的描述,阐释了Silverlight在微软用户体验(UX)计划中的地位。 非常重要的一点是,在Silverlight运行的客户端机器并不需要安装.NET。运行Silverlight所需的必要资源全都包含在Silverlight浏览器插件中。所有互操作场景都建立在Silverlight 2 Beta 2之上。Silverlight 2 Beta 2的新特性有:
- 框架语言(Visual Basic.NET, C#, IronPython, IronRuby)
- 存储分离
- JSON、REST、SOAP/WS-I、POX和RSS Web Services(也支持Sockets)
- 支持WCF
- ADO.NET数据服务
- LINQ to Objects和LINQ to XML
- Deep Zoom技术
- XML可编程
- 媒体内容保护
- 丰富的可管理控制框架这里列举了一个简单的crossdomain.xml文件的例子:“
1)所有的文件头或者2)Content-Type和SOAPAction头。
如果指定domain="*"任何领域发出的对文档的访问请求都会获得准许,但如果明确制定域名,比如domain="*.microsoft.com",那么只有指定领域发出的访问请求才能获得准许。Silverlight策略文件的格式描述可以参见:Network Security Access Restrictions in Silverlight 2“这里列举了一个简单的crossdomain.xml文件的例子:“Make a Service Available Across Domain Boundaries””。请注意本文中涉及的所有实例中,clientaccesspolicy.xml和crossdomain都必须置于域的根目录下。
图6:http://localhost:8081/clientaccesspolicy.xml
REST服务实例
REST (REpresentational State Transfer)这个概念是2000年Roy Thomas Fielding在他的博士论文中首先提出的。得益于REST本身的简单和普遍熟知的事实-万维网有REST架构的缘故,REST的发展迅猛。REST原则基于一下几点:
- 所有资源对应一个标识
- 表述(方法)是标准的
- 资源可有多重表述
- 资源的访问和传输由连接器封装, 连接器有: 客户端, 服务器, 缓存, 解析器和通道
- 无状态通信
REST能够迅速流行得益于它的简单和被广泛熟知。可以简单地把REST看作是:通过对URI的操作来改变资源的状态。
“纯REST”构想包括如下理念,即:1)所有事物都可以由拥有地址的资源来表示 2)对于资源只需要四种操作行为:创建、获取、更新和销毁。
“REST-to-HTTP映射”,这是许多人看待REST的方式。这种看法和“纯REST”的理念相同,只是URIs对应了资源地址,HTTP协议的GET、PUT、POST和DELETE则对应了四种操作。
当一个POX服务没有遵循“纯REST”架构,这种解决方案有时被称作“低REST”。可能会有多种自定义的操作而不是标准的4种操作。自定义操作是通过POST HTTP方法中的参数而非HTTP的特定方法来完成操作。
尽管REST开发和维护都比较简单,但它并不处理消息安全、事务、路由以及消息,这些更象是WS_I SOAP web服务负责处理的事务。 Silverlight中的SOAP网络服务也不处理消息安全、事务、路由以及消息。Silverlight无法象自动生成SOAP代理那样来自动生成REST代理。
HTTP方法
大多数REST的实现使用了下表所示的HTTP方法,由这些方法对底层的资源进行创建、获取、更新和销毁(CRUD)操作。
图7:HTTP方法
Silverlight仅支持GET和POST 这两个HTTP方法。一些防火墙对PUT和DELETE HTTP方法的使用也设置了一定的限制。
需要指出的很重要的一点是,真正的RESTful的服务仅仅能够用GET和POST HTTP方法来创建(遵循了以上列出的所有REST规则),换句话说,REST架构并不一定要对HTTP做特定的映射。Google’s GData X-Http-Method-Override头就是一例。
如果web服务在POST中解析X-HTTP-Method-Override头,那么可以在HTTP头中添加下列这些覆写的方法来完成PUT和DELETE操作:
- X-HTTP-Method-Override: PUT
- X-HTTP-Method-Override: DELETE
另外一个解决浏览器不支持PUT和DELETE HTTP的方法是在Silverlight控制器所在的页面使用异步的JavaScript和XML(AJAX)。在JavaScript事件中使用XMLHttpRequest可以做到通过HTML Bridge在正确的时间发送正确的HTTP方法。MSDN的一篇文章HTML Bridge: Interaction Between HTML and Managed Code详细讲解了该方法的实现。这种技术只有在HTML页面、“.xap”文件和服务端点在同一个领域内的时候才有效。
REST方案的定义:WADL和XSD
REST的一个局限性是schema是未知的,而且可能会有变化;再次验证REST服务可没那么简单。
Web Application Development Language(WADL)可以代替WSDL来支持特定的RESTful web服务,但目前没有得到广泛认可。
XML Schema Definition(XSD)文件可以作为REST服务中任何给定资源的“协议”来使用。
Java REST支持
许多工具、框架和集成开发环境都支持RESTful服务的开发。NetBeans Java集成开发环境就完全集成了1)从实体自动产生REST服务 2)集成REST服务测试(NetBeans Getting Started with RESTful Web Services on GlassFish)。 Eclipse集成开发环境也支持REST服务的开发(Eclipse REST support in STP)。JSR 311,提供RESTful Web服务的Java API,目前支持HTTP的PUT和DELETE方法。Jersey是遵循了JSP311的一个开源参考实现。
Silverlight .NET REST支持
Silverlight通过如下方式来支持REST:
- Web客户端类(例如,使用DownloadStringCompleted(GET)和UploadStringAsync与UploadStringAsync(POST)方法), 或者 HttpWebRequest类(更难使用,但可以激活一些高阶应用)。在这个实例中我们只使用简单而直接的WebClient类。
- 使用上面提到的HTML桥
- 使用AJAX,通过JavaScript和XMLHTTP对象或者AJAX工具包
创建请求URI的技术有很多种。使用XML消息体时,可用XmlSerialzer或者LINQ-toXml(System.Xml.Linq)。 使用JSON消息体时,可用DataContractJsonSerializer或者LINQ-to-JSON(System.Json)。 使用RSS/Atom消息体时,请参照如下内容。
图8:REST互操作性架构
从这个REST的例子,我们可以理解到目前Java REST实现与Silverlight协同工作的方式,同时也可以看到这种互操作方式的局限性。NetBeans 6.1版本能够根据Entity类自动生成REST服务。比方说,我们通过NetBeans创建一个简单的REST服务来访问某个数据库的一个数据表(也就是资源)。我们要访问的这个表DiscountCodes,有一个String字段DiscountCode和一个integer字段Rate。
图9:表DiscountCode
REST动作概要:
总体来说,在这个例子中,我们用到的HTTP方法(REST动作)有:
- GET: http://localhost:8081/resouces/discountCodes
- 返回所有DiscountCode记录的列表
- GET: http://localhost:8081/resouces/discountCodes/A/
- 返回DiscountCode“A”
- POST: http://localhost:8081/resouces/discountCodes
- 创建一条DiscountCode记录
图10:POST XML
GET: http://localhost:8081/resouces/discountCodes
这个Silverlight应用首先通过请求/resource/discountCode URI来实现“GET”(DownloadStringCompleted)操作。
图11:GET所有的discountCode
我们在这里提供整个XML的内容,response的内容因此一览无疑。接下来,只要在之前的URI基础上进一步指定/A/,得到了一个单独的资源。
GET: http://localhost:8081/resouces/discountCodes/A/
图12:GET资源/A/
POST: http://localhost:8081/resouces/discountCodes
现在通过拷贝新获得的/A/资源并在POST文本框中创建一个资源/D/来加入一个新的资源。
图13:POST资源/D/
确认GET URI中已经添加了/D/,然后点击GET按钮来创建了资源。
图14:GET (验证) 资源/D/
Get_Xml_Click和Post_Click事件这两个事件都通过WebClient来与Java服务通信。为清晰起见,这里我们省去了例外处理的部分。
图 15:Page.xaml.cs
“Get_Click”事件中,发送的请求中包含了getUri文本框中的内容,而后,回复的XML内容则显示在TextBox_GET的文本框中。
“Post_Click”事件中,发送的请求中包含了getUri文本框中的内容,而后,回复的XML内容则显示在TextBox_POST文本框中。
图16:Page.xml
由于在Silverlight既没有PUT也没有DELETE HTTP方法,因此这样的REST实现无法更新或者删除资源,但REST实现仍然可以利用POST方法来实现资源的更新和删除。>Why REST Failed一文就专门讨论了由于大多数浏览器不支持PUT和DELETE而带来的REST在浏览器兼容性方面的限制问题。
聚合(RSS)服务实例
远程站点聚合2.0(RSS)是一个轻量的发布-订阅标准,通常订阅诸如blog之内的内容。RSS最先由Netscape开发,而现在,RSS2.0实际上就是RSS标准。原子聚合格式已经通过了IETF的标准化程序,并且有一个ITEF RFC来描述原子种子(Atom feed)是什么以及如何解析。大多数聚合站点都支持这两种格式。
Silverlight有一个专为聚合而编译的动态链接库System.ServiceModel.Syndication.dll(Silverlight Syndication)。聚合种子和聚合项都包含在这一框架中。
我们举一个“选举”的例子,客户端需要异步访问RSS服务种子来查看更新的种子内容。Silverlight客户端通过种子的URI来访问一个简单的Java RSS种子。
图17:聚合交互架构
由于结果本身就是XML,所有Silverlight控件仅需要3行代码就能jiexi种子结果放到中。
图 18:聚合(RSS 2.0)阅读器
在OpenReadCompleted事件调用之后,回复结果被保存到XmlReader当中,然后被加载到SyndicationFeed。SyndicationFeed则以XAML的形式被绑定到itemList控件。为清晰起见,这里我们省去了例外处理的部分。
图 19: Page.xaml.cs
图 20: Page.xaml
有关Silverlight聚合的更多内容,请参见Accessing Syndication Feeds with Silverlight以及Databinding and the SyndicationFeed class。
SOAP Web服务实例
Web Services Interoperability Organization (WS-I )定义的web服务标准建立在Simple Object Access Protocol (SOAP)基础上。SOAP是一个基于XML的协议,使得消息可以通过HTTP/HTTPS协议来传递。W3C的Web Services Architecture文件奠定了SOAP Web服务的基础。如果基于Java的SOAP Web服务已经存在,那么为该服务创建代理就非常直接了当,然后就好在Visual Studio中运用这个服务了。需要注意的是,在web服务中采用引入复杂的数据类型会带来很大的麻烦,尤其是在设计Java-.NET交互的情况下。 Java SOAP web服务采用的数据类型应当能够映射到.NET所支持的数据类型上。
调试Web服务也存在很多问题。像Fiddler web调试代理或Web Development Helper这样的工具在调试Web服务时就非常有用。
除了WS-I Basic Profile,Silverlight对WS-*不提供任何支持,“但如果自己动手实现必要的协议的话,还是可以调用这些服务的”(参见Accessing SOAP Services)。Silverlight 支持WS-I Basic Profile 1.0和SOAP 1.1 over HTTP。需要指出的是,SOAP的错误会在客户端抛出一个例外,但不会指明导致该错误的详细信息。
Silverlight支持WCF(Windows Communication Foundation) 客户端技术,这种客户端可以调用SOAP服务,但所能调用的服务还是会受到互操作方面的限制。Silverlight可以调用的SOAP服务可以是WCF服务、ASP.NET Web服务(“.asmx”),或某些Java服务。
Silverlight Web服务团队的blog上有一篇文章——Detailed Overview of Silverlight 2 Beta 2 Web Service Features,概括了Silverlight 2 Beta 2在web服务方面的一些优化。对于使用SOAP的Java-Silverlight的互操作,最主要的顾虑是:代理是否能够编译;web服务是否存在数据类型或者序列化方面的问题。
配置
ServiceReference.ClientConfig的配置支持,使得修改绑定或地址都不需要重新编译Silverlight控件。
图21:ServiceReference.ClientConfig
Windows Communications Foundation(WCF)
Silverlight 2 Beta 2中有一个“支持Silverlight的WCF服务”模板,如果用这个模板创建WCF服务的话,服务自动就被配置使用Silverlight所支持的协议。BasicHttpBinding使用HTTP之上的SOAP1.0,是一个符合WS-I Basic Profile 1.1的绑定。参见“Accessing SOAP Services”。
ASMX
“Add Service Reference”会根据Address:label为所引用的服务创建一个ASMX代理。
图22:添加服务引用
SOAP错误处理
“由于Web浏览器的限制,客户端无法接收SOAP错误。当服务发送出错误时,客户端会抛出一个例外,但无法指明发生错误的详细信息。(Accessing SOAP Services)
图23:SOAP Web 服务互操作性架构
NetBeans中,一个简单的web服务节点有如下方法:FindAll和find。为清晰起见,这里我们省去例外处理的部分。
图24:Page.xaml.cs
Visual Studio中指向Java Soap2Service端点的代理如下:
图25:Soap2Service代理引用
web服务其实就是一个调用,这个调用通过请求参数来传递,之后又负责接收web服务的响应。Web服务的响应(String)被绑定到XAML。而XAML又通过Silverlight控件显示到用户界面。
图26:SOAP Web服务-Find All
图27:SOAP Web服务 - Find 'B'
代理对象有一个绑定和一个端点。代理用findAllAsnyc事件来发送findAll请求,用FindAllCompleted事件接收FindAll的响应。findAll的响应以XAML显示在findAllResponse文本框中。为清晰起见,这里我们省去例外处理的部分。
图28: Page.xaml.cs
图29:Page.xaml
代理的配置信息来自ServiceReference.ClientConfig。ServiceReferences.ClientConfig配置文件支持多个端点的配置。
修改ServiceReferences.ClientConfig不需要重新编译Silverlight应用程序。
图30: ServiceReferences.ClientConfig
总结
本文展开论述了Silverlight/Java的互操作性。简单SOAP web服务、REST服务和聚合种子服务都可与Silverlight互操作。SOAP web服务有着潜在的数据序列化问题,仅仅提供基本的WS-I支持,因此相对比较复杂,但只要Visual Studio Silverlight客户端中能够成功创建代理,服务也能很快实现。在开发REST服务的时候,开发者必须依赖于文档,而文档却可能没有更新或不是很准确。已有的的那些仅使用GET和POST HTTP方法的RESTful实现与Silverllight的互操作工作得最好。对于查询类型的服务来说,REST是个不错的选择;而SOAP则更适合CRUD型的服务。聚合服务实现起来相对简单,而且限制很少。
开发者可以选择任意的互操作形式,找到最合适他们特定的开发和部署环境的方式。
需要了解的一个基本概念是,Silverlight运行在浏览器上下文中。跨域、跨方案和跨区问题、浏览器连接数的限制以及对不同MIME类型的支持等等,对Silverlight和运行在浏览器平台上的任何应用来说,都是在开发和部署过程中不可忽视的问题。对于浏览器上各种各样的应用开发,最基本的共同点往往是定义浏览器局限性的基准。
非常有趣的是,在Silverlight 2 RTM中将很有可能支持JAXB-style对象引用,其支持方式与 .NET框架3.5 SP1(DataContractSerializer)的支持类似。
转载地址:http://www.infoq.com/cn/articles/silverlight-java-interop