引言
代表性状态(REST)体系结构样式提供了壁垒较低的使用Web服务门槛。典型REST样式应用程序的外部接口包括大量统一资源标识符(Uniform Resource Identifier,URI)可寻址资源和一些操作,如创建、读取、更新和删除(CRUD)等。这样的体系结构样式的优势是其简单性。
开发人员兼作家Paul Prescod将REST Web服务定义为“使用HTTP协议的语法和语义将其功能完全作为一组URI可寻址资源提供的Web服务”(请参见参考资料)。可以将万维网本身视为REST样式的例子。位于Web底层的HTTP协议使用统一资源定位符Uniform Resource Locator,URL)来表示资源和一些广泛使用的HTTP方法,如用于操作资源的GET、POST、PUT、HEAD和delete。这个简单的体系结构样式通过重用Web的松散耦合与分布式基础设施来提供可伸缩性和交互能力。
本文给出了一个银行业务服务示例,该服务将贷款利率发布到类似于Bankrate的聚合器网站(请参见参考资料)。聚合器网站通常从多个不同的提供商收集信息,并将其聚合为客户端Mashup。这也称为透明地组合,可以将其视为组合应用程序。为了方便地创建此类Mashup,服务提供商需要公开一个简化接口。REST体系结构样式可很好地满足此要求。
本文建议使用Facade组件 来向现有SOAP样式的Web服务提供REST样式的接口。本文描述组件所需的功能,并将这些功能捕获在Rational Software Architect可重用资产规范(Reusable Asset Specification,RAS)模式中。此模式由端点和现有Web服务的操作进行参数化。可以将此模式转换为可部署的Java 2 Enterprise Edition(J2EE)Servlet实现,以调用现有Web服务。这个生成的Servlet支持所需的REST样式功能,如浏览器缓存、资源内容格式协商和使用SOAP Attachment for Java(SAAJ)标准进行大型附件的HTTP流化。
有关URI、CRUD、Mashup、Facade模式、SOAP样式的Web服务、RAS模式、SAAJ及其他资源的更多信息,请参见参考资料。
REST样式的Facade组件所需的功能
用于指示REST样式的资源的可自定义URL
REST体系结构样式支持采用URL来提供对细粒度资源的访问。例如,在贷款应用程序中,银行在特定日期提供的贷款利率就是一个必需的资源。通过使用不同的URL表示每个细粒度资源,可允许其他应用程序(如电子邮件)方便地引用这些资源。这还同时支持使用Web 2.0技术(如Ajax)进行客户端资源组合。因此,Web服务Facade组件允许应用程序开发人员自定义表示资源的URL。
用于操作资源的HTTP方法,如GET、POST、delete、PUT、TRACE和OPTIONS。
REST样式的Web服务允许通过数量较少的常用操作访问资源,如用于获取资源的表示形式、获取关于资源的信息以及操作资源的各个独立操作。HTTP协议已经定义了这样的操作集(GET、POST、PUT等等)。(有关HTTP方法的更多信息,请参见参考资料。)Facade组件支持使用这些HTTP方法。请注意,针对SOAP Web服务的Web服务描述语言(Web Service Description Language,WSDL)1.1仅支持HTTP POST方法。WSDL 2.0通过包括对 HTTP GET 绑定的支持对此进行了补充,但在WebSphere Application Server V6.1中尚不支持WSDL 2.0。另请注意,HTTP delete、PUT、TRACE和OPTIONS方法使用并不频繁,而且经常被防火墙阻止。
资源表示形式和内容格式协商
URL所访问的每个资源都可以使用不同的形式加以表示,具体取决于访问资源的客户机。客户机可以是台式计算机上的HTML浏览器或其他SOAP Web服务或Ajax或JavaScript Object Notation(JSON)客户机(请参见参考资料)。Facade组件查询HTTP请求的Accept Header字段来确定客户机所需的响应格式,并随后以所需的格式提供资源。
资源表示形式的浏览器与网关代理缓存
REST样式的结果最常用于使用HTTP GET方法访问资源。对于HTTP GET请求,REST样式的Web服务可以设置HTTP响应Header字段来提供指示信息,以确定Web浏览器是否缓存返回的资源表示形式以及缓存多长时间、要缓存的资源表示形式的有效或失效策略是什么。通过支持响应缓存,可提高应用程序的可伸缩性。Facade组件会相应地将HTTP Header Cache-Control响应指令设置为PUBLIC、PRIVATE等。
使用SAAJ来调用SOAP样式的Web服务
SOAP样式的Web服务以XML形式返回响应,而此格式通常是REST样式客户机需要的资源表示形式。所以,Facade组件可避免由于直接访问XML格式的SOAP响应消息而造成的不必要的取消封送开销。为此,Facade组件使用SAAJ来调用现有的Web服务。SAAJ还可以通过HTTP对Web服务响应中附件内的大量数据进行流化。
简单而言,RAS模式是一种可重用资产,描述给定上下文中重复出现的问题的解决方案(请参见参考资料部分,其中提供了指向IBM Pattern Solution网站的链接)。可以使用IBM Rational Software Architect(RSA)之类的工具来捕获模式,以自动化解决方案开发工作。下面的部分将对RAS模式进行描述,用以捕获REST样式的Web服务Facade的所需功能。
下载和安装模式
请参见下载部分,其中提供了打包为可重用资产的一个REST模式和一个转换插件。通过以下步骤将此资产安装到RSA中:
·解压缩下载包。
·在Rational Software Architect中,通过File>Import窗口导入RESTFeature.ras资产。在Import窗口中选择RAS Asset类型。通过向导页来导入此资产。
·单击Help>About IBM Rational Software Development Platform。
·要验证插件是否已成功安装,请在Plug-ins Details窗口中找到RESTPattern Plug-in和RESTPatternTransform Plug-in,如图1中所示。
图1. 查看插件
创建模式实例
遵循以下步骤来创建模式实例:
·依次单击Window>Show View>PatternExplorer,打开Pattern Explorer视图。此模式应该在WEB2.0组下显示,如图2中所示。
图2. 在Pattern Explorer视图中查看新模式
·在RSA中打开Modeling透视图,并创建新建模项目。
·在新创建的项目中创建一个空白UML模型。
·将模式拖放到新创建的模型中。
现在已经创建了RESTWebServiceFacade模式的实例。下一步是填充参数。
指定模式参数
在RESTWebServiceFacade模式实例中指定以下参数:
表1. REST模式支持的参数
图3显示模式的一个实例。可以使用以下参数将此实例作为现有Web服务的Facade使用:
·端点为http://localhost:9081/RESTRouter/service/RatesFacade。
·操作名为queryRate。
·命名空间为http://ejbs。
·参数为prodId(具有类似于Mortgage的值)和prodType(具有类似于30-year fixed的值)。
用于访问REST样式的资源的示例URL:ttp://localhost:9080/bank/rateprodId=Mortgage&prodType=30-year%20fixed,其中servletPath是在/rate参数中指定的,而contextPath是作为/bank指定的。服务响应中支持的资源表示格式为XML和HTTP,如果公开提供就可以对响应进行缓存。
图3. RESTWebServiceFacade模式的模式实例
将模式转换为J2EE Servlet
清遵循以下步骤将模式转换为J2EE Servlet:
·创建动态Web项目。
·右键单击模式,并选择Transform>Pattern to WebServiceFacadeServlet,如图4中所示。
·指定在步骤1中新创建的Web项目。
图4. 调用转换
图5 显示了生成的包装Servlet。
图5. 生成的包装Servlet
更新、部署和调用生成的J2EE Servlet代码
遵循以下步骤,以更新生成的代码,从而支持其他资源表示格式和从SOAP消息提取附件:
·查看生成的Servlet代码:
通过扩展J2EE HttpServlet抽象类和实现对应的J2EE Servlet方法(如doGet、doPost和dodelete),可在生成的Facade Servlet中支持指定的HTTP方法。
清单1显示了生成的代码,该代码使用SAAJ调用了现有的Web服务。
清单1. 用于使用SAAJ调用现有SOAP Web服务的代码示例
MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); //create objects for the message parts SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope(); SOAPBody body = envelope.getBody(); envelope.getHeader().detachNode(); //Populate the body //create the main element and namespace SOAPElement bodyElement = body.addChildElement(envelope .createName(operation, "req", ns)); //Add content bodyElement.addChildElement("prodid").addTextNode(para0); bodyElement.addChildElement("prodtype").addTextNode(para1); //Save the message message.saveChanges(); URL endpoint = new URL(endPoint); SOAPMessage respMsg = connection.call(message, endpoint) |
清单2. 用于设置浏览器缓存HTTP Header的代码示例
response.setHeader("Cache-Control", "public");
清单3显示用于解析相应资源表示形式和恰当设置MIME内容类型的生成代码。
清单3. 有关资源表示形式和内容格式协商的代码示例
String[] pattern_accepts={"text/xml"}; String req_accepts = request.getHeader("Accept"); RESTResourceRepresentationContext repContext = new RESTResourceRepresentationContext(); String format_decision = repContext.getAcceptFormat(pattern_accepts, req_accepts); response.setContentType(format_decision); repContext.registerDefaultStrategies(); repContext.generateAppropriateResourceRepresentation(respMsg,printer); |
支持新的资源表示格式。为了创建自定义应答格式,请通过从RESTResponseStrategy类继承并向RESTResourceRepresentationContext类的registerStrategy()操作进行注册来创建新策略。
使用SAAJ获取大型附件,以便通过HTTP进行流化。可以使用SoapMessage#getAttachments()方法来从SOAP信封提取附件。可以将采用这种方式提取的附件通过HTTP响应对象发送到客户机。
·将Web项目部署到J2EE 1.4应用服务器中,如图5中所示。
·使用从参数构造的URL调用Facade :http://localhost:9080/
·按图6中的示例所示的方式在REST服务客户机中查看操作的结果。
图6. 使用Web浏览器访问REST包装
模式插件的源代码
可以对模式插件的源代码(请参见下载)进行修改,以捕获您的开发组织创建REST样式的Web服务Facade的最佳实践。
尽管REST体系结构样式在很多情况下都非常具有吸引力,但可能在某些情况下并不适合。以下就是一些这样的例子:
对于非结构化请求或响应格式,优先选用远程过程调用类型的服务调用。
例如,在两个帐户之间进行资金转帐的事务型Web服务就是如此。缺省情况下使用REST样式的Web服务并不提供事务完整性支持,但可以将此支持添加到SOAP样式的Web服务。
服务调用中涉及到多个协议。
例如,考虑要支持同步样式接口而不是异步样式接口。
需要通过业务流程执行语言(Business Process execution Language,BPEL)集成到业务流程。
目前BPEL流程并不支持REST样式的接口。只有服务组件体系结构(Service Component Architecture,SCA)组件可以编排在BPEL流程中。
结束语
REST样式Web服务Facade提供某些所需的功能,如多资源格式表示形式、支持响应的浏览器缓存以及支持PUT、TRACE和delete等其他HTTP方法。本文提供的RAS模式资产捕获用于开发REST样式的Web服务Facade的最佳实践。