2000年Rest被Roy Fielding提出来的,我对Roy Fielding的印象有以下几个.
一是RoyFielding做为Http协议的起草者,在Http协议发布没多久跳起来说这个世界上很多人对于Http的使用是错误的,所以他说大家应该用Rest.
二是没多久RoyFielding做为Rest思想的启蒙者,在Rest被人接受并被广泛使用没多久跳起来说这个世界上很多人对Rest的使用是错误的..
所以我在PPT上选了柏拉图的一句话做为副标题,"思想永远是宇宙的统治者".
二 Rest
Rest本身的内容比我想象的多的多,大致列出来几个关键点如下:
1.满足以下的Constraints:
Constraints代码
- Client–server
- Stateless
- Cacheable
- Layered system
- Code on demand (optional)
- Uniform interface
2.设计接口时候的原则
Principles 代码
- Identification of resources
- Manipulation of resources through these representations
- Self-descriptive messages
- Hypermedia as the engine of application state
3.Rest希望实现的目标
Key goals代码
- Scalability of component interactions
- Generality of interfaces
- Independent deployment of components
- Intermediary components to reduce latency, enforce security and encapsulate legacy systems
以上内容都摘自Wiki,稍微整理了一下.感觉以上的内容都很深刻,所以我简单的列出来了我认为理解Rest的重要的地方.
4.Rest对于我们来说
写道
Every Things is a Resource.
Every Resouce has a ID.
We Can Use Http Meothod(Get/Post/Put/Delete) Handle Resource.
简单说,再设计接口的时候,
第一个想到的是,我要提供的资源是什么.
第二个想到的是,这个资源的展现形式是什么.
第三个想到的是,这个资源上封装的操作是什么
我觉得这些就足够了.Rest和Soap比有太多的好处了,还有利于SEO(感谢搜索组的两位大神说到两点,一个是Url Path本身占的权重比Parameters高,一个是Url链接本身的权重就比较高.)
如果是设计一个键盘精灵的接口的话(之前博客中提到过键盘精灵,这里的主要的功能是查找拼音中以"Q"开头的产品列表),仿照前段时间四处流行的对比手法写出来三种不同风格的Url接口设计
写道
普通风格 /prompt/list.do?query=g&count=10&searchFrom=product
文艺风格
/prompt/product/g/10
2B风格 /?method=getProductPromt&query=g&count=10&searchFrom=product
这时候已经有很多人在争论Rest有没有用处,还有不少人在讨论Rest的适用场景了,还有人问到比较实际的问题,比如说多参数怎么解决.
我觉得Rest本身提供的是一种方式,怎么样让这种方式变得更艺术还真的取决于你怎么去使用他.设计Rest的接口更是一种艺术形式,最简单的例子,我要看一个人的某个时间段发表的文章列表,可能会有以下几种设计方式:
1. /person/xdyl/20000101-20000202
2. /person/xdyl/start/20000101/end/20000202
3./person/xdyl?start=20000101&end/20000202
4./person/xdyl/20000101/20000202/
哪种方式好就看个人喜好了吧.搜了一下SpringMVC也没看到有这种解决方案,之前还以为会有/{a}-{b}/这样的方式.
如果其他的朋友有好的解决方案还请多指点.
三 Spring MVC实现.
我觉得Spring MVC的实现很简单.大概牵涉到两个地方.
1.Spring 本身怎么支持从Path中获取变量的.
2.系统怎么区分一个请求应该被Spring拦截到还是应该被直接访问的静态资源
第一个问题很简单.贴段代码如下:
Java代码
- @Controller
- @RequestMapping(value = "/contact")
- public class ContactController {
- private static final Log log = LogFactory.getLog(ContactController.class);
- @RequestMapping(value = "/{contact}", method = RequestMethod.GET)
- public String getContactdetail(@PathVariable Long contact, Model model) {
- Contact c = this.contactService.getContact(contact);
- if (c == null) {
- c = new Contact();
- }
- model.addAttribute("code", 0);
- model.addAttribute("contact", c);
- return "/contact/detail/jmodel";
- }
- }
增删改查分别修改"method "以对应Http的四种方法(Post,Delete,Put,Get)就好了.
变量直接通过@PathVariable 就可以拿到.
第二个问题我理解起来也很简单.用UrlRewriter将所有的请求分成两种.动态请求加一个前缀"/app/",配置Spring的拦截器只拦截这种请求. 静态资源以前缀"/r/"开始,请求路径不变.
这样任何一个请求都会乖乖的分成两部分,是以"/r/"开始的就不会走Spring,不是以"/r/"开头全转成"/app/",交给Spring处理.
主要配置如下
web.xml 写道
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Spring只拦截/app/的请求-->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
urlrewrite.xml 写道
<urlrewrite default-match-type="wildcard">
<rule>
<from>/r/**</from>
<to>/r/$1</to>
</rule>
<rule>
<from>/**</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
UrlRewrite可以用其它有同样功能的任意代替,Apache神马的最讨厌了.
最后附上我用到的UrlRewriter的Pom文件.不记得在哪儿看到的了,先贴上来再说.
pom.xml 写道
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>3.1.0</version>
</dependency>
Over,这个东西不是一个很详细的Spring配置说明.我记得第一次配的时候还是出了不少问题的.不过我觉得源码如果公开的话就什么问题都么有了~
等等看什么时候可以把Labs的源码公开了.