自己动手写淘宝开放平台:Rop(将WebService REST进行到底!!)

http://www.iteye.com/topic/1121252

简介


最近在开发自己公司网站的开放API服务,较深入地研究了 TOP(Taobao Open Platform:淘宝开放平台 http://api.taobao.com )。在接触过这么多的网站API中,发现TOP真的是做得非常不错,结构清晰明了,使用简单轻便。但是TOP没有开源,搞不到TOP的源码。所以只能“自己动手,丰衣足食”了。
我基于Spring MVC 3.0进行开发,居然3天就完工了,现在已经在公司中使用,大家的反映相当不错,现已整理了一份PPT文档,奉献给大家。同时,我将其命名为ROP(Rest Open Platform),已经在github中发布,地址是:

https://github.com/itstamen/rop

iteye的Rop群组已经改变很大,最新消息请加入群中了解:http://rop.group.iteye.com/


欢迎大家讨论!
ROP的快速开发完成,其实是借力于Spring MVC灵活的扩展性和其提供了各种好用且强大的工具类,ROP基于Spring MVC,在处理流程上进行了重新的组织,但是在实现上基本上直接利用Spring提供的工具类和组件,所以实现并不太难。

5分钟快速入门

以下是基于ROP开发Web Service的简单例子:
例子说明:
根据userName/password/salary这三个属性创建一个新用户。
第1步:创建请求对象
Java代码 收藏代码
  1. packagecom.sample.rop.request;
  2. importcom.stamen.rop.RopRequest;
  3. importorg.springframework.format.annotation.NumberFormat;
  4. importjavax.validation.constraints.DecimalMax;
  5. importjavax.validation.constraints.DecimalMin;
  6. importjavax.validation.constraints.Pattern;
  7. publicclassCreateUserRequestextendsRopRequest{
  8. @Pattern(regexp="\\w{4,30}")//①通过JSR303注解指定验证规则
  9. privateStringuserName;
  10. @Pattern(regexp="\\w{6,30}")//②
  11. privateStringpassword;
  12. @DecimalMin("1000.00")
  13. @DecimalMax("100000.00")
  14. @NumberFormat(pattern="#,###.##")//③
  15. privatelongsalary;
  16. //getterandsetter...
  17. }

①、②及③处通过JSR303注解指定请求参数的合法性规则,如果请求参数值违反了规则,ROP会产生相应的错误报文。

第2步:创建响应对象
Java代码 收藏代码
  1. packagecom.sample.rop;
  2. importcom.rop.RopResponse;
  3. importjavax.xml.bind.annotation.XmlAccessType;
  4. importjavax.xml.bind.annotation.XmlAccessorType;
  5. importjavax.xml.bind.annotation.XmlAttribute;
  6. importjavax.xml.bind.annotation.XmlRootElement;
  7. @XmlAccessorType(XmlAccessType.FIELD)//①
  8. @XmlRootElement(name="sampleRopResponse1")
  9. publicclassCreateUserResponseimplementsRopResponse{
  10. @XmlAttribute//②
  11. privateStringuserId;
  12. @XmlAttribute//③
  13. privateStringcreateTime;
  14. //getterandsetter...
  15. }

①、②及③处通过JAXB(即JSR222 已经包含在JDK6中)的注解对响应对象的流化规则进行设置,ROP会自动将响应的对象流化成相应的响应报文,支持XML和JSON格式,仅需通过format的参数进行指定返回格式即可。

第3步:创建服务方法
Java代码 收藏代码
  1. packagecom.sample.rop;
  2. importcom.rop.ApiMethod;
  3. importcom.sample.rop.request.CreateUserRequest;
  4. importcom.sample.rop.response.CreateUserResponse;
  5. importorg.springframework.stereotype.Service;
  6. @Service//①服务方法所在的类必须标注成Bean
  7. publicclassUserRestService{
  8. @ApiMethod("sample.user.add")//②指定对应的API方法
  9. publicRopResponseaddUser(CreateUserRequestrequest){
  10. CreateUserResponseresponse=newCreateUserResponse();
  11. //addcreaetnewuserhere...
  12. response.setCreateTime("20120101010101");
  13. response.setUserId("1");
  14. returnresponse;
  15. }
  16. }

首先,服务方法所在的类必须标注成Bean,如①所示,然后在服务方法中标注ROP的@ApiMethod注解,如②所示,这里的
@ApiMethod(" sample.user.add ")表示,addUser(...)将处理?method= sample.user.add &...的服务请求。
处理方法的签名规约如下:
  • 入参必须继承于RopRequest父类,也可以为空(无入参);
  • 返回值必须实现RopResponse接口,由于一般的服务方法都拥有错误的可能,因此一般直接使用RopResponse作为返回类型,这样不管是正确的响应对象,还是错误的响应对象,都可以满足签名的要求。

这样,所有服务端的开发工作就完成了!下面来写客户端调用的代码。

编写调用的客户端

由于现在ROP还没有提供客户端调用包,所以我们直接使用Spring的RestTemplate来写:
Java代码 收藏代码
  1. packagecom.sample.rop;
  2. importcom.rop.validation.DefaultRopValidator;
  3. importorg.springframework.util.LinkedMultiValueMap;
  4. importorg.springframework.util.MultiValueMap;
  5. importorg.springframework.web.client.RestTemplate;
  6. importjava.util.ArrayList;
  7. publicclassUserRestServiceClient{
  8. publicstaticvoidmain(String[]args){
  9. RestTemplaterestTemplate=newRestTemplate();
  10. MultiValueMap<String,String>form=newLinkedMultiValueMap<String,String>();
  11. form.add("method","sample.user.add");//<--指定服务名
  12. form.add("appKey","00001");//<--指定客户端应用的key,我们在rop.appSecret.properties
  13. //中预定义了两个appKey,服务端可通过实现AppSecretManager
  14. //定义自己的appKey管理策略。
  15. form.add("v","1.0");
  16. form.add("sessionId","test");//真实系统时,必须是真正的sessionId.
  17. form.add("format","xml");
  18. form.add("locale","en");
  19. form.add("userName","tomson");
  20. form.add("password","123456");
  21. form.add("salary","2,500.00");
  22. //对请求参数进行签名,对于"00001"appKey的密钥是"abcdeabcdeabcdeabcdeabcde"
  23. Stringsign=DefaultRopValidator.sign(newArrayList<String>(
  24. form.keySet()),form.toSingleValueMap(),
  25. "abcdeabcdeabcdeabcdeabcde");
  26. form.add("sign",sign);
  27. //发送请求,调用服务
  28. Stringresponse=restTemplate.postForObject(
  29. "http://localhost:9080/router",form,String.class);
  30. System.out.println("response:\n"+response);
  31. }
  32. }

这里的系统级参数,我们直接模仿TOP设计,说明如下:
No parmName paramType required desc
1. method String Y API method name(sample.user.add)
2. appKey String Y design to application's appKey,you can define in rop.appSecret.properties which is in classpath.
3. v String Y API version,now only support:1.0。
4. sign String Y API parameters's sing,Use SHA1 encryption algorithm
5. sessionId String N use's sessionId.you can provide a rest api so client can get it and maintain locally.
6. format String N Optional, designated response format. The default XML,currently support for an XML format, json
7. locale String N locale,such lick cn_ZH,en...

参见: http://open.taobao.com/doc/detail.htm?id=111
启用服务端的服务后,执行该测试,将返回:
Xml代码 收藏代码
  1. <?xmlversion="1.0"encoding="utf-8"standalone="yes"?>
  2. <sampleRopResponse1createTime="20120101010101"userId="1"/>

如果将format参数设置为json,则其返回的报文为:
Javascript代码 收藏代码
  1. {"sampleRopResponse1":{"userId":"1","createTime":"20120101010101"}}

如果将salary参数改为"aaa",则将返回错误报文(假设format为xml):
Xml代码 收藏代码
  1. <?xmlversion="1.0"encoding="utf-8"standalone="yes"?>
  2. <errorsolution="InvalidArguments"message="InvalidArguments"code="34">
  3. <subErrors>
  4. <subError>
  5. <code>isv.parameters-mismatch:salary-and-aaa</code>
  6. <message>incomingparametersalaryandaaadoesnotmatch,both
  7. haveacertaincorrespondencebetween</message>
  8. </subError>
  9. </subErrors>
  10. </error>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值