微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

自己动手写淘宝开放平台: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. package com.sample.rop.request;  
  2. import com.stamen.rop.RopRequest;  
  3. import org.springframework.format.annotation.NumberFormat;  
  4. import javax.validation.constraints.DecimalMax;  
  5. import javax.validation.constraints.DecimalMin;  
  6. import javax.validation.constraints.Pattern;  
  7.   
  8. public class createuserRequest extends RopRequest {  
  9. @Pattern(regexp = "\\w{4,30}")//① 通过JSR303注解指定验证规则  
  10. private String userName;  
  11. @Pattern(regexp = "\\w{6,0)">//②  
  12. private String password;  
  13. @DecimalMin("1000.00")  
  14. @DecimalMax("100000.00")  
  15. @NumberFormat(pattern = "#,###.##")//③  
  16. private long salary;  
  17. //getter and setter...  
  18. }  

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

第2步:创建响应对象 package com.sample.rop;  
  • import com.rop.RopResponse;  
  • 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 = "sampleRopResponse1")  
  • class createuserResponse implements RopResponse{  
  •     @XmlAttribute     private String userId;  
  • private String createTime;  
  •        ①、②及③处通过JAXB(即JSR222 已经包含在JDK6中)的注解对响应对象的流化规则进行设置,ROP会自动将响应的对象流化成相应的响应报文,支持XML和JSON格式,仅需通过format的参数进行指定返回格式即可。 
    第3步:创建服务方法
    import com.rop.ApiMethod;  
  • import com.sample.rop.request.createuserRequest;  
  • import com.sample.rop.response.createuserResponse;  
  • import org.springframework.stereotype.Service;  
  • @Service//① 服务方法所在的类必须标注成Bean  
  • class UserRestService {  
  • @ApiMethod("sample.user.add")//②指定对应的API方法  
  • public RopResponse addUser(createuserRequest request) {  
  •         createuserResponse response = new createuserResponse();  
  •         //add creaet new user here...  
  •         response.setCreateTime("20120101010101");  
  •         response.setUserId("1");  
  •         return response;  
  •     }  
  •    首先,服务方法所在的类必须标注成Bean,如①所示,然后在服务方法中标注ROP的@ApiMethod注解,如②所示,这里的 
    @ApiMethod(" sample.user.add ")表示,addUser(...)将处理?method= &...的服务请求。 
    处理方法的签名规约如下: 
      
    • 入参必须继承于RopRequest父类,也可以为空(无入参);
    • 返回值必须实现RopResponse接口,由于一般的服务方法都拥有错误的可能,因此一般直接使用RopResponse作为返回类型,这样不管是正确的响应对象,还是错误的响应对象,都可以满足签名的要求。  
      
       这样,所有服务端的开发工作就完成了!下面来写客户端调用代码。 
    编写调用的客户端    由于现在ROP还没有提供客户端调用包,所以我们直接使用Spring的RestTemplate来写: 
    import com.rop.validation.DefaultRopValidator;  
  • import org.springframework.util.LinkedMultiValueMap;  
  • import org.springframework.util.MultiValueMap;  
  • import org.springframework.web.client.RestTemplate;  
  • import java.util.ArrayList;  
  • class UserRestServiceClient {  
  • static void main(String[] args) {  
  •         RestTemplate restTemplate = new RestTemplate();  
  •         MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();  
  •         form.add("method""sample.user.add");//<--指定服务名  
  •         form.add("appKey""00001");//<--指定客户端应用的key,我们在rop.appSecret.properties  
  •                                     //中预定义了两个appKey,服务端可通过实现AppSecretManager  
  • //定义自己的appKey管理策略。  
  •         form.add("v""1.0");  
  •         form.add("sessionId""test");//真实系统时,必须是真正的sessionId.  
  •         form.add("format""xml");  
  •         form.add("locale""en");  
  •         form.add("userName""tomson");  
  •         form.add("password""123456");  
  •         form.add("salary""2,500.00");  
  • //对请求参数进行签名,对于"00001" appKey的密钥是"abcdeabcdeabcdeabcdeabcde"  
  •         String sign = DefaultRopValidator.sign(new ArrayList<String>(  
  •                             form.keySet()), form.toSingleValueMap(),  
  •                             "abcdeabcdeabcdeabcdeabcde");  
  •         form.add("sign", sign);  
  • //发送请求,调用服务  
  •         String response = restTemplate.postForObject(  
  •                 "http://localhost:9080/router", form, String.class);  
  •         System.out.println("response:\n" + response);  
  •    这里的系统级参数,我们直接模仿TOP设计,说明如下: 
    No parmName    paramType  required   desc
    1. method          String          Y   API method name(sample.user.add)
    2. appKey     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     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代码  

    收藏代码

      <?xml version="1.0" encoding="utf-8" standalone="yes"?>  
    1. <sampleRopResponse1 createTime="20120101010101" userId="1"/>  

  •   如果将format参数设置为json,则其返回的报文为: 
    Javascript代码  

    收藏代码

      {"sampleRopResponse1":{"userId":"1","createTime":"20120101010101"}}  

      如果将salary参数改为"aaa",则将返回错误报文(假设format为xml): 
    error solution="Invalid Arguments" message="Invalid Arguments " code="34">  
  •     subErrors         subError             code>isv.parameters-mismatch:salary-and-aaa</message>incoming parameter salary and aaa does not match, both   
  • have a certain correspondence betweenerror>  
  • 版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

    相关推荐