用Spring MVC自己动手写TOP(Taobao Open Platform)
程序员文章站
2022-05-25 10:31:50
...
最近在开发自己公司网站的开放API服务,较深入地研究了TOP(Top Open Platform:淘宝开放平台[url]http://api.taobao.com[/url])。在接触过这么多的网站API中,发现TOP真的是做得非常不错,结构清晰明了,使用简单轻便。但是TOP便没有开源,搞不到TOP的源码。所以只能“自己动手,丰衣足食”了。
我基于Spring MVC 3.0进行开发,居然3天就完工了,现在已经在公司中使用,大家的反映相当不错,现已整理了一份PPT文档,奉献给大家。同时,我将其命名为ROP(Rest Open Platform),已经在github中发布,地址是:
[url]https://github.com/itstamen/rop[/url]
欢迎大家讨论!
ROP的快速开发完成,其实是借力于Spring MVC灵活的扩展性和其提供了各种好用且强大的工具类,ROP基于Spring MVC,在处理流程上进行了重新的组织,但是在实现上基本上直接利用Spring提供的工具类和组件,所以实现并不太难。
以下是基于ROP开发Web Service的简单例子:
[b]例子说明:[/b]
根据userName/password/salary这三个属性创建一个新用户。
[b]第1步:创建请求对象[/b]
①、②及③处通过JSR303注解指定请求参数的合法性规则,如果请求参数值违反了规则,ROP会产生相应的错误报文。
[b]第2步:创建响应对象[/b]
①、②及③处通过JAXB(即JSR222 已经包含在JDK6中)的注解对响应对象的流化规则进行设置,ROP会自动将响应的对象流化成相应的响应报文,支持XML和JSON格式,仅需通过format的参数进行指定返回格式即可。
[b]第3步:创建服务方法[/b]
首先,服务方法所在的类必须标注成Bean,如①所示,然后在服务方法中标注ROP的@ApiMethod注解,如②所示,这里的
@ApiMethod("[b]sample.user.add[/b]")表示,addUser(...)将处理?method=sample.user.add&...的服务请求。
处理方法的签名规约如下:
[list]
[*]入参必须继承于RopRequest父类,也可以为空(无入参);
[*]返回值必须实现RopResponse接口,如果一般的服务方法都拥有错误的可能,因此一般直接使用RopResponse作为返回类型,这样不管是正确的响应对象,还是错误的响应对象,都可以满足签名的要求。
[/list]
这样,所有服务端的开发工作就完成了!下面来写客户端调用的代码,由于现在ROP还没有提供客户端调用包,所以我们直接使用Spring的RestTemplate来写:
这里的系统级参数,我们直接模仿TOP设计,说明如下:
[table]
|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...|
[/table]
参见:
启用服务端的服务后,执行该测试,将返回:
如果将format参数设置为json,则其返回的报文为:
如果将salary参数改为"aaa",则将返回错误报文(假设format为xml):
ROP使用到了Spring很多底层的功能,有兴趣的iteyeer可以看我的《Spring3.x企业应用开发实战》,书中有较详细的介绍。也欢迎各位高手参加ROP开源项目中,可以在iteye中给我短消息报名参加。谢谢!
我基于Spring MVC 3.0进行开发,居然3天就完工了,现在已经在公司中使用,大家的反映相当不错,现已整理了一份PPT文档,奉献给大家。同时,我将其命名为ROP(Rest Open Platform),已经在github中发布,地址是:
[url]https://github.com/itstamen/rop[/url]
欢迎大家讨论!
ROP的快速开发完成,其实是借力于Spring MVC灵活的扩展性和其提供了各种好用且强大的工具类,ROP基于Spring MVC,在处理流程上进行了重新的组织,但是在实现上基本上直接利用Spring提供的工具类和组件,所以实现并不太难。
以下是基于ROP开发Web Service的简单例子:
[b]例子说明:[/b]
根据userName/password/salary这三个属性创建一个新用户。
[b]第1步:创建请求对象[/b]
package com.sample.rop.request;
import com.stamen.rop.RopRequest;
import org.springframework.format.annotation.NumberFormat;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Pattern;
public class CreateUserRequest extends RopRequest {
@Pattern(regexp = "\\w{4,30}")//① 通过JSR303注解指定验证规则
private String userName;
@Pattern(regexp = "\\w{6,30}")//②
private String password;
@DecimalMin("1000.00")
@DecimalMax("100000.00")
@NumberFormat(pattern = "#,###.##")//③
private long salary;
//getter and setter...
}
①、②及③处通过JSR303注解指定请求参数的合法性规则,如果请求参数值违反了规则,ROP会产生相应的错误报文。
[b]第2步:创建响应对象[/b]
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")
public class CreateUserResponse implements RopResponse{
@XmlAttribute//②
private String userId;
@XmlAttribute//③
private String createTime;
//getter and setter...
}
①、②及③处通过JAXB(即JSR222 已经包含在JDK6中)的注解对响应对象的流化规则进行设置,ROP会自动将响应的对象流化成相应的响应报文,支持XML和JSON格式,仅需通过format的参数进行指定返回格式即可。
[b]第3步:创建服务方法[/b]
package com.sample.rop;
import com.rop.ApiMethod;
import com.sample.rop.request.CreateUserRequest;
import com.sample.rop.response.CreateUserResponse;
import org.springframework.stereotype.Service;
@Service//① 服务方法所在的类必须标注成Bean
public 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("[b]sample.user.add[/b]")表示,addUser(...)将处理?method=sample.user.add&...的服务请求。
处理方法的签名规约如下:
[list]
[*]入参必须继承于RopRequest父类,也可以为空(无入参);
[*]返回值必须实现RopResponse接口,如果一般的服务方法都拥有错误的可能,因此一般直接使用RopResponse作为返回类型,这样不管是正确的响应对象,还是错误的响应对象,都可以满足签名的要求。
[/list]
这样,所有服务端的开发工作就完成了!下面来写客户端调用的代码,由于现在ROP还没有提供客户端调用包,所以我们直接使用Spring的RestTemplate来写:
package com.sample.rop;
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;
public class UserRestServiceClient {
public 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设计,说明如下:
[table]
|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...|
[/table]
参见:
http://open.taobao.com/doc/detail.htm?id=111
启用服务端的服务后,执行该测试,将返回:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<sampleRopResponse1 createTime="20120101010101" userId="1"/>
如果将format参数设置为json,则其返回的报文为:
{"sampleRopResponse1":{"userId":"1","createTime":"20120101010101"}}
如果将salary参数改为"aaa",则将返回错误报文(假设format为xml):
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error solution="Invalid Arguments" message="Invalid Arguments " code="34">
<subErrors>
<subError>
<code>isv.parameters-mismatch:salary-and-aaa</code>
<message>incoming parameter salary and aaa does not match, both
have a certain correspondence between</message>
</subError>
</subErrors>
</error>
ROP使用到了Spring很多底层的功能,有兴趣的iteyeer可以看我的《Spring3.x企业应用开发实战》,书中有较详细的介绍。也欢迎各位高手参加ROP开源项目中,可以在iteye中给我短消息报名参加。谢谢!
下一篇: 【原创】使用Jersey体验REST