精华帖 (8) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-08-08
最后修改:2012-08-28
引用 Rop,即Rapid Open Platform,是一个参考淘宝开放平台(TOP Taobao Open Platform)的平台设计思路,充分借鉴Spring MVC的技术架构原理开发的一个快速服务开放平台开源框架项目,可以让您迅速构建成熟的SOA服务平台。它不同于传统的SOAP Web Service和Rest Web Service这些Web Service 技术型框架,Rop是一个应用型的Web Service平台框架,它不但可以方便快捷地开发一个个Web Service服务,还提供了服务平台领域问题的整体解决方案。因此,... 传统的Web Service框架帮助你建造房子,而Rop框架帮助您建造城市。 Rop项目文档前后写了一个多月,在写的过程中发现很多功能不完善的,又回过头了改项目,此种反复多次,现在Rop开源项目的文档已经差不多了,将陆续在iteye此发出,希望对大家有帮助。在Rop项目的开发过程中得到了众多iteye网友的有力帮助,收到了很多很好的整改的意见,在此对他们的奉献和帮助表示诚挚的感谢,这些网友包括但不限于: melin kellokitty 風一樣的男子 lioliang 木木的爱情童话 devotionalist ericliang Rop相关资源: 1.github:https://github.com/itstamen/rop 2.群组:http://rop.group.iteye.com/ 3.Rop开发手册:开发手册 目录 1.快速了解Rop 2.请求服务模型 3.应用授权及验证 4.服务会话管理 5.错误处理模型 6.响应报文控制 7.文件上传 8.服务安全控制 9.拦截器及事件体系 10.性能调优 11.开发客户端SDK 12.参考资料 Rop概述 Rop是Rapid Open Platform的简称,它不同于一般纯技术型的Web Service框架(如CXF,Jersey等),Rop致力于构建开放服务平台的框架,您可以使用Rop开发类似于淘宝开放服务平台这样的服务平台。Rop充分借鉴了当前大型网站的开放服务平台的设计思路,汲取了它们成功的实践经验,对开放服务平台的很多应用层领域问题给出了解决方案,开发者可以直接使用这些解决方案,也可以在此基础上进行个性化扩展。 Rop功能架构 CXF和Jersey是纯技术纯的Web Service框架,而在Rop中,Web Service只是核心,它提供了开发服务平台的诸多领域问题的解决方案:如应用认证、会话管理、安全控制、错误模型、版本管理、超时限制等。 下面通过图1了解一下Rop框架的整体结构: 图1 从图1中,可以看到Rop所提供的大部分功能都是偏“应用层”的,传统技术型的Web Service框架是不会僭越到这些“应用层”的问题的。但是,在实际开发中,这些应用层的问题不但不可避免,而且非常考验开发者的设计经验,此外,这些工作还会占用较大的开发工作量。Rop力图让开发者从这些复杂的工作中解脱出来,让他们可以真正聚焦服务平台业务逻辑的实现上。 Rop技术架构 Rop在技术实现上充分借鉴了Spring MVC的框架设计理念和实现技术,首先RopServlet类似于Spring MVC的DispatcherServlet,是Rop的门面Servlet,负责截获HTTP服务请求转由Rop框架处理。具体技术架构通过图2描述: 图2 Rop的配置信息统一在Spring配置文件中通过rop Schema命名空间定义。ServiceRouter是Rop框架的核心,它负责协调各组件的交互并最终完成服务处理的工作。RopServlet在启动时会从Spring容器中搜索出ServiceRouter的Bean实例并注册之。 在服务请求到达后,RopServlet截获请求并转交给ServiceRouter处理,ServiceRouter将服务请求封装成一个的RopRequestContext对象,RopRequestContext包含了服务请求的所有信息。而后,ServiceRouter使用SecurityManager检查服务请求的安全性,只有通过了SecurityManager的安全检查,才会调用目标服务处理方法执行服务,否则将阻止请求并返回错误响应信息。 完成SecurityManager的安全检查后,ServiceRouter通过ServiceMethodAdapter对目标的服务方法发起调用。由于具体服务方法的签名各不相同,因此必须采用反射机制进行适配调用。当返回响应对象后,ServiceRouter使用RopMarshaller将响应对象编组为特定的响应报文返回给客户端。 您会发现Rop的顶级框架接口类在Spring MVC中都能找到对应的对象:RopServlet对应DispatcherServlet,ServiceMethodAdapter对应HandlerAdapter,RopMarshaller对应ViewResolver,而ServiceRouter承担了HandlerMapping和部分DispatcherServlet的角色。因此,如果您在学习Spring MVC的框架后,理解Rop框架的实现原理将变得非常轻松。 使用Rop开发一个服务 将Rop项目克隆到本地 由于Rop托管在github (www.github.com)中,为了获取最新的Rop项目,必须在您的系统中安装Git客户端软件,我们推荐使用msysgit,它能够让我们在Windows系统中像Linux一样使用Git。 从http://code.google.com/p/msysgit/下载并安装git客户端msysgit,然而在开始菜单中找到并打开Git Bash,在命令窗口运行如下命令: 引用 cd /d/agileSpring/
git clone git://github.com/itstamen/rop.git 第一行命令将当前工作目录移到某个系统目录下,需要注意的是:由于msysgit是在Windows中模拟的Linux环境,所以D:/对应为/d/。第二行命令,从github中克隆一个Rop项目到您本地机中。 图3 使用以下的Maven命令构建rop和rop-sample项目,打开DOS窗口,移到rop及rop-sample项目的pom.xml所在的目录,执行构建命令: 引用 mvn clean install
还可以通过如下Maven命令,启动rop-sample项目(首先移到rop-sample的pom.xml所在的目录): 引用 mvn jetty:run
如果你不想下载最新的Rop项目,上面的过程就可以免除了,您直接在项目的pom.xml中引入Rop类包就可以了,如下所示: <dependency> <groupId>com.bookegou</groupId> <artifactId>rop</artifactId> <version>1.0</version> </dependency> Rop的发布包已经发布到Maven的核心仓库中(org.sonatype.oss),因此你可以直接使用在pom.xml引用即可。 开发一个服务方法 rop-sample项目中有一个com.rop.sample.UserService的服务类,我们就通过这个服务类了解开发基于Rop的Web Service服务的过程。 UserService.java package com.rop.sample; import com.rop.RopRequest; import com.rop.annotation.NeedInSessionType; import com.rop.annotation.ServiceMethod; import com.rop.annotation.ServiceMethodBean; import com.rop.sample.response.LogonResponse; import com.rop.session.SimpleSession; //①标注Rop的注解,使UserService成为一个Rop的服务Bean @ServiceMethodBean public class UserService { //②使该服务方法成为一个Web Service的方法。 @ServiceMethod(method = "user.getSession", version = "1.0", needInSession = NeedInSessionType.NO) public Object getSession(LogonRequest request) { //创建一个会话 SimpleSession session = new SimpleSession(); session.setAttribute("userName",request.getUserName()); request.getRequestContext().addSession("mockSessionId1", session); //返回响应 LogonResponse logonResponse = new LogonResponse(); logonResponse.setSessionId("mockSessionId1"); return logonResponse; } 由于ServiceMethodBean注解已经标注了Spring的@Service注解(即org.springframework.stereotype.Service),因此标注@ServiceMethodBean的类也相当于标注了@Service,Rop扩展Spring @Service的目的是为了引入新的功能特性。 在类方法处标注@ServiceMethod,即可将该方法发布成一个Rop的Web Service服务。@ServiceMethod注解拥有丰富的参数,value值是必须的,它用于指定服务方法名称,version用于指定服务方法的版本号,needInSession用于说明该服务方法是否要工作在会话环境中。更多参数的说明,详见本章后续内容,这里只要了解这么多就可以了。 由于任何一个服务方法都是由请求/响应对构成的,所以在Rop的服务方法的签名是有约定的:入参必须为RopRequest接口或其子类,出参可以是任何标注了JSR 222注解的对象。这种约定在一定程度上限制了方法签名的灵活性,但是由于Rop强烈建议对所有请求参数都做服务端校验,因此把参数封装成一个Java类并在类属性中标注JSR 303注解,就可以在参数绑定时实施数据校验了。来看一下LogonRequest的类: LogonRequest.java package com.rop.sample.request; import com.rop.AbstractRopRequest; import com.rop.annotation.IgnoreSign; import javax.validation.constraints.Pattern; public class LogonRequest extends AbstractRopRequest{ @Pattern(regexp = "\\w{4,30}") private String userName; @IgnoreSign @Pattern(regexp = "\\w{6,30}") private String password; //get/setter } Rop采用“契约优于配置”的原则:请求参数按名称匹配的方式自动绑定到请求对象的属性上。在请求对象类中,Rop使用JSR 303(Bean Validation )注解描述请求参数的校验规则,如果请求参数值违反了校验规则,Rop将驳回服务请求,直接返回相应的错误报文给客户端。 服务方法必须返回一个响应对象,Rop框架会将其转换成响应报文。在这个例子中,如果服务正常执行,将返回一个LogonResponse的对象。LogonResponse类定义如下: package com.rop.sample.response; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "logonResponse") public class LogonResponse{ @XmlAttribute private String sessionId; … } Rop使用JSR 222(即JAXB)注解描述响应类到响应报文的转换映射关系,响应对象最终将以响应报文的形式(XML或JSON)返回给客户端。 如何在Spring中配置Rop Rop基于Spring框架工作,可以看成是一个Spring的子项目。Rop提供了一个扩展的Spring Schema命令空间,使用Rop Schema在Spring配置文件配置好Rop环境非常方便: sampleRopApplicationContext.xml <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:rop="http://www.bookegou.com/schema/rop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.bookegou.com/schema/rop ①引入Rop Schema定义文件 http://www.bookegou.com/schema/rop/rop-1.0.xsd"> <!--② 扫描Spring Bean--> <context:component-scan base-package="com.rop.sample"/> <!--③启动Rop框架 --> <rop:annotation-driven/> </beans> 首先,引入Rop的Schema命名空间,如①处所示。由于Rop的服务类必须是一个Bean,所以需要声明Spring的扫描器,将标注了Spring Bean注解的类加载为Spring容器中的Bean。由于@ServiceMethodBean注解本身标注了Spring的@Service,所以所有标注了@ServiceMethodBean的类也会自动成为Spring的Bean。最后,我们通过一个简单<rop:annotation-driven/>即可启动Rop框架,如③所示。 在web.xml配置Rop 由于客户端需要通过HTTP访问Rop服务,因此Rop必须依附于一个Web Servlet容器。和Spring MVC的DispatcherServlet类似,Rop提供了一个com.rop.RopServlet,在web.xml中配置好RopServlet,这样Rop就可以接收HTTP的服务请求了: web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:sampleRopApplicationContext.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!--①定义一个RopServlet,并指定其映射的URL--> <servlet> <servlet-name>rop</servlet-name> <servlet-class> com.rop.RopServlet </servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>rop</servlet-name> <url-pattern>/router</url-pattern> </servlet-mapping> </web-app> 由于Rop是基于Spring工作的,因此首先必须在web.xml中配置一个Spring容器,然后再通过RopServlet指定Rop的工作的路径。 引用 值得注意的是,Rop依赖于Spring框架而非Spring MVC框架,因此你的Web应用框架是可以自由选择的,如Struts、JSF等。
访问Rop服务 在rop-sample项目中,我们已经配置maven-jetty-plugin插件,因此IDE的环境下可以直接运行这个插件:jetty->jetty:run 启动rop-sample项目。在控制台中,您将可以看到rop-sample启动的输出信息。(也可以在DOS窗口下执行 mvn jetty:run命令启动) 下面开发一个访问rop-sample服务的客户端程序: package com.rop.sample; import com.rop.client.CompositeResponse; import com.rop.client.DefaultRopClient; import com.rop.client.RopClient; import com.rop.client.ClientRequest; import com.rop.sample.request.LogonRequest; import com.rop.sample.response.LogonResponse; import org.testng.annotations.Test; import static org.testng.Assert.*; public class UserServiceClient { //① public static final String SERVER_URL = "http://localhost:8088/router"; public static final String APP_KEY = "00001"; public static final String APP_SECRET = "abcdeabcdeabcdeabcdeabcde"; private RopClient ropClient = new DefaultRopClient(SERVER_URL, APP_KEY, APP_SECRET); @Test public void createSession() { //②构造请求对象 LogonRequest ropRequest = new LogonRequest(); ropRequest.setUserName("tomson"); ropRequest.setPassword("123456"); //③对服务发起调用并获取响应结果 CompositeResponse response = ropClient.buildClientRequest() .get(ropRequest, LogonResponse.class, "user.getSession", "1.0"); assertNotNull(response); assertTrue(response.isSuccessful()); assertNotNull(response.getSuccessResponse()); assertTrue(response.getSuccessResponse() instanceof LogonResponse); assertEquals(((LogonResponse) response.getSuccessResponse()).getSessionId(), "mockSessionId1"); } } 大凡Web Service框架都会提供服务的客户端,DefaultRopClient即是Rop提供了客户端,您可以非常方便地通过DefaultRopClient以面向对象的方式访问服务获取响应对象,无需关心服务请求和响应报文的底层细节。 运行以上测试方法,通过报文抓取工具,我们可以看到“真实”的底层通信细节,如下图4所示: 图4 由此可见,DefaultRopClient会自动将LogonRequest请求对象拼装成一个请求URL,同时,在接收到响应报文后,会将响应报文反编组成一个响应对象。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-08-08
用Rop进行开发很简单,支持!!!
|
|
返回顶楼 | |
发表时间:2012-08-10
看到标题以为是 Ruby on Rails,
进来才知道是 Rapid Open Platform 以前接触过一些,这次正好借楼主的帖子学习下, 感谢楼主,支持 |
|
返回顶楼 | |
发表时间:2012-08-10
忘了说,
楼主的那边spring书很不错, |
|
返回顶楼 | |
发表时间:2012-08-10
最后修改:2012-08-10
xiaoyuqi00 写道 看到标题以为是 Ruby on Rails,
进来才知道是 Rapid Open Platform 以前接触过一些,这次正好借楼主的帖子学习下, 感谢楼主,支持 原来的解释是 Rest Open Platform,觉得不达意,后来改成Rapid Open Platform。还好整体没有变。 |
|
返回顶楼 | |
发表时间:2012-08-10
最后修改:2012-08-11
每次逛雄哥的博客都有新发现。
|
|
返回顶楼 | |
发表时间:2012-08-10
@ServiceMethod 对应方法参数有点限制,可以改进参考spring mvc 参数绑定方法
|
|
返回顶楼 | |
发表时间:2012-08-11
melin 写道 @ServiceMethod 对应方法参数有点限制,可以改进参考spring mvc 参数绑定方法
谢谢melin的建议!这个我本来是想在这处版本改过来的,不过时间比较赶,计划在下个版本改。 有一个问题就是,Web Service的所有参数一般都需要校验,如果采用如下的签名: Object addUser(String userName,String password){...} 参数的校验规则只能打在入参上,方法入参反而会比较复杂,如果把它们封装成一个RopRequest,在属性声明处打校验规则,则服务方法的签名就干净多了。这也是我本版本没有下决心去改的一个原因。 |
|
返回顶楼 | |
发表时间:2012-10-25
看后一个感觉,很好的框架,离平台太远了。平台最基本的如何让其他人方便的接入,这个接入不只是APP,还包括新API。
|
|
返回顶楼 | |
发表时间:2013-06-27
stamen 写道 引用 Rop,即Rapid Open Platform,是一个参考淘宝开放平台(TOP Taobao Open Platform)的平台设计思路,充分借鉴Spring MVC的技术架构原理开发的一个快速服务开放平台开源框架项目,可以让您迅速构建成熟的SOA服务平台。它不同于传统的SOAP Web Service和Rest Web Service这些Web Service 技术型框架,Rop是一个应用型的Web Service平台框架,它不但可以方便快捷地开发一个个Web Service服务,还提供了服务平台领域问题的整体解决方案。因此,... 传统的Web Service框架帮助你建造房子,而Rop框架帮助您建造城市。 Rop项目文档前后写了一个多月,在写的过程中发现很多功能不完善的,又回过头了改项目,此种反复多次,现在Rop开源项目的文档已经差不多了,将陆续在iteye此发出,希望对大家有帮助。在Rop项目的开发过程中得到了众多iteye网友的有力帮助,收到了很多很好的整改的意见,在此对他们的奉献和帮助表示诚挚的感谢,这些网友包括但不限于: melin kellokitty 風一樣的男子 lioliang 木木的爱情童话 devotionalist ericliang Rop相关资源: 1.github:https://github.com/itstamen/rop 2.群组:http://rop.group.iteye.com/ 3.Rop开发手册:开发手册 目录 1.快速了解Rop 2.请求服务模型 3.应用授权及验证 4.服务会话管理 5.错误处理模型 6.响应报文控制 7.文件上传 8.服务安全控制 9.拦截器及事件体系 10.性能调优 11.开发客户端SDK 12.参考资料 Rop概述 Rop是Rapid Open Platform的简称,它不同于一般纯技术型的Web Service框架(如CXF,Jersey等),Rop致力于构建开放服务平台的框架,您可以使用Rop开发类似于淘宝开放服务平台这样的服务平台。Rop充分借鉴了当前大型网站的开放服务平台的设计思路,汲取了它们成功的实践经验,对开放服务平台的很多应用层领域问题给出了解决方案,开发者可以直接使用这些解决方案,也可以在此基础上进行个性化扩展。 Rop功能架构 CXF和Jersey是纯技术纯的Web Service框架,而在Rop中,Web Service只是核心,它提供了开发服务平台的诸多领域问题的解决方案:如应用认证、会话管理、安全控制、错误模型、版本管理、超时限制等。 下面通过图1了解一下Rop框架的整体结构: 图1 从图1中,可以看到Rop所提供的大部分功能都是偏“应用层”的,传统技术型的Web Service框架是不会僭越到这些“应用层”的问题的。但是,在实际开发中,这些应用层的问题不但不可避免,而且非常考验开发者的设计经验,此外,这些工作还会占用较大的开发工作量。Rop力图让开发者从这些复杂的工作中解脱出来,让他们可以真正聚焦服务平台业务逻辑的实现上。 Rop技术架构 Rop在技术实现上充分借鉴了Spring MVC的框架设计理念和实现技术,首先RopServlet类似于Spring MVC的DispatcherServlet,是Rop的门面Servlet,负责截获HTTP服务请求转由Rop框架处理。具体技术架构通过图2描述: 图2 Rop的配置信息统一在Spring配置文件中通过rop Schema命名空间定义。ServiceRouter是Rop框架的核心,它负责协调各组件的交互并最终完成服务处理的工作。RopServlet在启动时会从Spring容器中搜索出ServiceRouter的Bean实例并注册之。 在服务请求到达后,RopServlet截获请求并转交给ServiceRouter处理,ServiceRouter将服务请求封装成一个的RopRequestContext对象,RopRequestContext包含了服务请求的所有信息。而后,ServiceRouter使用SecurityManager检查服务请求的安全性,只有通过了SecurityManager的安全检查,才会调用目标服务处理方法执行服务,否则将阻止请求并返回错误响应信息。 完成SecurityManager的安全检查后,ServiceRouter通过ServiceMethodAdapter对目标的服务方法发起调用。由于具体服务方法的签名各不相同,因此必须采用反射机制进行适配调用。当返回响应对象后,ServiceRouter使用RopMarshaller将响应对象编组为特定的响应报文返回给客户端。 您会发现Rop的顶级框架接口类在Spring MVC中都能找到对应的对象:RopServlet对应DispatcherServlet,ServiceMethodAdapter对应HandlerAdapter,RopMarshaller对应ViewResolver,而ServiceRouter承担了HandlerMapping和部分DispatcherServlet的角色。因此,如果您在学习Spring MVC的框架后,理解Rop框架的实现原理将变得非常轻松。 使用Rop开发一个服务 将Rop项目克隆到本地 由于Rop托管在github (www.github.com)中,为了获取最新的Rop项目,必须在您的系统中安装Git客户端软件,我们推荐使用msysgit,它能够让我们在Windows系统中像Linux一样使用Git。 从http://code.google.com/p/msysgit/下载并安装git客户端msysgit,然而在开始菜单中找到并打开Git Bash,在命令窗口运行如下命令: 引用 cd /d/agileSpring/
git clone git://github.com/itstamen/rop.git 第一行命令将当前工作目录移到某个系统目录下,需要注意的是:由于msysgit是在Windows中模拟的Linux环境,所以D:/对应为/d/。第二行命令,从github中克隆一个Rop项目到您本地机中。 图3 使用以下的Maven命令构建rop和rop-sample项目,打开DOS窗口,移到rop及rop-sample项目的pom.xml所在的目录,执行构建命令: 引用 mvn clean install
还可以通过如下Maven命令,启动rop-sample项目(首先移到rop-sample的pom.xml所在的目录): 引用 mvn jetty:run
如果你不想下载最新的Rop项目,上面的过程就可以免除了,您直接在项目的pom.xml中引入Rop类包就可以了,如下所示: <dependency> <groupId>com.bookegou</groupId> <artifactId>rop</artifactId> <version>1.0</version> </dependency> Rop的发布包已经发布到Maven的核心仓库中(org.sonatype.oss),因此你可以直接使用在pom.xml引用即可。 开发一个服务方法 rop-sample项目中有一个com.rop.sample.UserService的服务类,我们就通过这个服务类了解开发基于Rop的Web Service服务的过程。 UserService.java package com.rop.sample; import com.rop.RopRequest; import com.rop.annotation.NeedInSessionType; import com.rop.annotation.ServiceMethod; import com.rop.annotation.ServiceMethodBean; import com.rop.sample.response.LogonResponse; import com.rop.session.SimpleSession; //①标注Rop的注解,使UserService成为一个Rop的服务Bean @ServiceMethodBean public class UserService { //②使该服务方法成为一个Web Service的方法。 @ServiceMethod(method = "user.getSession", version = "1.0", needInSession = NeedInSessionType.NO) public Object getSession(LogonRequest request) { //创建一个会话 SimpleSession session = new SimpleSession(); session.setAttribute("userName",request.getUserName()); request.getRequestContext().addSession("mockSessionId1", session); //返回响应 LogonResponse logonResponse = new LogonResponse(); logonResponse.setSessionId("mockSessionId1"); return logonResponse; } 由于ServiceMethodBean注解已经标注了Spring的@Service注解(即org.springframework.stereotype.Service),因此标注@ServiceMethodBean的类也相当于标注了@Service,Rop扩展Spring @Service的目的是为了引入新的功能特性。 在类方法处标注@ServiceMethod,即可将该方法发布成一个Rop的Web Service服务。@ServiceMethod注解拥有丰富的参数,value值是必须的,它用于指定服务方法名称,version用于指定服务方法的版本号,needInSession用于说明该服务方法是否要工作在会话环境中。更多参数的说明,详见本章后续内容,这里只要了解这么多就可以了。 由于任何一个服务方法都是由请求/响应对构成的,所以在Rop的服务方法的签名是有约定的:入参必须为RopRequest接口或其子类,出参可以是任何标注了JSR 222注解的对象。这种约定在一定程度上限制了方法签名的灵活性,但是由于Rop强烈建议对所有请求参数都做服务端校验,因此把参数封装成一个Java类并在类属性中标注JSR 303注解,就可以在参数绑定时实施数据校验了。来看一下LogonRequest的类: LogonRequest.java package com.rop.sample.request; import com.rop.AbstractRopRequest; import com.rop.annotation.IgnoreSign; import javax.validation.constraints.Pattern; public class LogonRequest extends AbstractRopRequest{ @Pattern(regexp = "\\w{4,30}") private String userName; @IgnoreSign @Pattern(regexp = "\\w{6,30}") private String password; //get/setter } Rop采用“契约优于配置”的原则:请求参数按名称匹配的方式自动绑定到请求对象的属性上。在请求对象类中,Rop使用JSR 303(Bean Validation )注解描述请求参数的校验规则,如果请求参数值违反了校验规则,Rop将驳回服务请求,直接返回相应的错误报文给客户端。 服务方法必须返回一个响应对象,Rop框架会将其转换成响应报文。在这个例子中,如果服务正常执行,将返回一个LogonResponse的对象。LogonResponse类定义如下: package com.rop.sample.response; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "logonResponse") public class LogonResponse{ @XmlAttribute private String sessionId; … } Rop使用JSR 222(即JAXB)注解描述响应类到响应报文的转换映射关系,响应对象最终将以响应报文的形式(XML或JSON)返回给客户端。 如何在Spring中配置Rop Rop基于Spring框架工作,可以看成是一个Spring的子项目。Rop提供了一个扩展的Spring Schema命令空间,使用Rop Schema在Spring配置文件配置好Rop环境非常方便: sampleRopApplicationContext.xml <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:rop="http://www.bookegou.com/schema/rop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.bookegou.com/schema/rop ①引入Rop Schema定义文件 http://www.bookegou.com/schema/rop/rop-1.0.xsd"> <!--② 扫描Spring Bean--> <context:component-scan base-package="com.rop.sample"/> <!--③启动Rop框架 --> <rop:annotation-driven/> </beans> 首先,引入Rop的Schema命名空间,如①处所示。由于Rop的服务类必须是一个Bean,所以需要声明Spring的扫描器,将标注了Spring Bean注解的类加载为Spring容器中的Bean。由于@ServiceMethodBean注解本身标注了Spring的@Service,所以所有标注了@ServiceMethodBean的类也会自动成为Spring的Bean。最后,我们通过一个简单<rop:annotation-driven/>即可启动Rop框架,如③所示。 在web.xml配置Rop 由于客户端需要通过HTTP访问Rop服务,因此Rop必须依附于一个Web Servlet容器。和Spring MVC的DispatcherServlet类似,Rop提供了一个com.rop.RopServlet,在web.xml中配置好RopServlet,这样Rop就可以接收HTTP的服务请求了: web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:sampleRopApplicationContext.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!--①定义一个RopServlet,并指定其映射的URL--> <servlet> <servlet-name>rop</servlet-name> <servlet-class> com.rop.RopServlet </servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>rop</servlet-name> <url-pattern>/router</url-pattern> </servlet-mapping> </web-app> 由于Rop是基于Spring工作的,因此首先必须在web.xml中配置一个Spring容器,然后再通过RopServlet指定Rop的工作的路径。 引用 值得注意的是,Rop依赖于Spring框架而非Spring MVC框架,因此你的Web应用框架是可以自由选择的,如Struts、JSF等。
访问Rop服务 在rop-sample项目中,我们已经配置maven-jetty-plugin插件,因此IDE的环境下可以直接运行这个插件:jetty->jetty:run 启动rop-sample项目。在控制台中,您将可以看到rop-sample启动的输出信息。(也可以在DOS窗口下执行 mvn jetty:run命令启动) 下面开发一个访问rop-sample服务的客户端程序: package com.rop.sample; import com.rop.client.CompositeResponse; import com.rop.client.DefaultRopClient; import com.rop.client.RopClient; import com.rop.client.ClientRequest; import com.rop.sample.request.LogonRequest; import com.rop.sample.response.LogonResponse; import org.testng.annotations.Test; import static org.testng.Assert.*; public class UserServiceClient { //① public static final String SERVER_URL = "http://localhost:8088/router"; public static final String APP_KEY = "00001"; public static final String APP_SECRET = "abcdeabcdeabcdeabcdeabcde"; private RopClient ropClient = new DefaultRopClient(SERVER_URL, APP_KEY, APP_SECRET); @Test public void createSession() { //②构造请求对象 LogonRequest ropRequest = new LogonRequest(); ropRequest.setUserName("tomson"); ropRequest.setPassword("123456"); //③对服务发起调用并获取响应结果 CompositeResponse response = ropClient.buildClientRequest() .get(ropRequest, LogonResponse.class, "user.getSession", "1.0"); assertNotNull(response); assertTrue(response.isSuccessful()); assertNotNull(response.getSuccessResponse()); assertTrue(response.getSuccessResponse() instanceof LogonResponse); assertEquals(((LogonResponse) response.getSuccessResponse()).getSessionId(), "mockSessionId1"); } } 大凡Web Service框架都会提供服务的客户端,DefaultRopClient即是Rop提供了客户端,您可以非常方便地通过DefaultRopClient以面向对象的方式访问服务获取响应对象,无需关心服务请求和响应报文的底层细节。 运行以上测试方法,通过报文抓取工具,我们可以看到“真实”的底层通信细节,如下图4所示: 图4 由此可见,DefaultRopClient会自动将LogonRequest请求对象拼装成一个请求URL,同时,在接收到响应报文后,会将响应报文反编组成一个响应对象。 |
|
返回顶楼 | |