您的位置:首页 > 运维架构 > 网站架构

REST架构风格

2010-12-03 02:41 274 查看
前段时间第一次从同事那里听说了REST这个概念,当时是听的一头雾水,直到现在我觉得自己也不能说已经理解这个概念了,而且我觉得更主要的是观念的转变。关于什么才是实现异构的应用到应用通信的“正确”方式,一场争论正进行的如火如荼:当前主流的方式集中在基于SOAP、WSDL和WS-*规范的Web Services领域,现在开始有小部分人主张说更好的方式是REST,表述性状态转移(REpresentational State Transfer)的简称。

网上介绍REST的文章不少,不了解的可以搜搜看。

REST的几条关键原则列举如下:

1.为所有“事物”定义ID

对事物使用一致的命名规则(naming scheme)最主要的好处就是你不需要提出自己的规则——而是依靠某个已被定义,在全球范围中几乎完美运行,并且能被绝大多数人所理解的规则。如果在一个类似于Amazon.com的在线商城中,没有用唯一的ID(一个URI)标识它的每一件商品,可想而知这将是多么可怕的业务决策。

下面是一些你可能想到的URI的例子:
http://example.com/customers/1234 http://example.com/orders/2007/10/776654 http://example.com/orders/2007/11
2.将所有事物链接在一起

任何可能的情况下,使用链接指引可以被标识的事物(资源)。也正是超链接造就了现在的Web。

3.使用标准方法

GET、POST、DELETE、PUT

4.资源多重表述

针对不同的需求提供资源多重表述,客户端可以请求返回指定格式的资源如xml

上面的内容来源于http://www.infoq.com/cn/articles/rest-introduction

英文地址http://www.infoq.com/articles/rest-introduction

还有一篇文章Build RESTful web services using Spring 3介绍了如何利用spring 3构建REST风格应用。

下面借用下上篇文章的例子介绍下如何在Spring3下搭建REST应用,首先在web.xml

配置contextConfigLocation

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/rest-context.xml
</param-value>
</context-param>

<!-- This listener will load other application context file in addition to
rest-servlet.xml -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>


下面是在rest-servlet.xml中配置Spring MVC

<context:component-scan base-package="dw.spring3.rest.controller" />
<!--To enable @RequestMapping process on type level and method level-->
<bean class="org.springframework.web.servlet.mvc.annotation
.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation
.AnnotationMethodHandlerAdapter" />
<!--Use JAXB OXM marshaller to marshall/unmarshall following class-->
<bean id="jaxbMarshaller"
class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>dw.spring3.rest.bean.Employee</value>
<value>dw.spring3.rest.bean.EmployeeList</value>
</list>
</property>
</bean>
<bean id="employees" class=
"org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg ref="jaxbMarshaller" />
</bean>
<bean id="viewResolver" class=
"org.springframework.web.servlet.view.BeanNameViewResolver" />


Listing 3. EmployeeController控制器类

@Controller
public class EmployeeController {
@RequestMapping(method=RequestMethod.GET, value="/employee/{id}")
public ModelAndView getEmployee(@PathVariable String id) {
Employee e = employeeDS.get(Long.parseLong(id));
return new ModelAndView(XML_VIEW_NAME, "object", e);
}
}


Listing 4. EmployeeController in dw.spring3.rest.controller

[b]
@RequestMapping(method=RequestMethod.POST, value="/employee")
public ModelAndView addEmployee(@RequestBody String body) {
Source source = new StreamSource(new StringReader(body));
Employee e = (Employee) jaxb2Mashaller.unmarshal(source);
employeeDS.add(e);
return new ModelAndView(XML_VIEW_NAME, "object", e);
}
@RequestMapping(method=RequestMethod.PUT, value="/employee/{id}")
public ModelAndView updateEmployee(@RequestBody String body) {
Source source = new StreamSource(new StringReader(body));
Employee e = (Employee) jaxb2Mashaller.unmarshal(source);
employeeDS.update(e);
return new ModelAndView(XML_VIEW_NAME, "object", e);
}
@RequestMapping(method=RequestMethod.DELETE, value="/employee/{id}")
public ModelAndView removeEmployee(@PathVariable String id) {
employeeDS.remove(Long.parseLong(id));
List<Employee> employees = employeeDS.getAll();
EmployeeList list = new EmployeeList(employees);
return new ModelAndView(XML_VIEW_NAME, "employees", list);
}




[/b]

Listing 5. getAllEmployees in EmployeeController

@RequestMapping(method=RequestMethod.GET, value="/employees")
public ModelAndView getEmployees() {
List<Employee> employees = employeeDS.getAll();
EmployeeList list = new EmployeeList(employees);
return new ModelAndView(XML_VIEW_NAME, "employees", list);
}



Listing 6. EmployeeList class in dw.spring3.rest.bean

@XmlRootElement(name="employees")
public class EmployeeList {
private int count;
private List<Employee> employees;
public EmployeeList() {}

public EmployeeList(List<Employee> employees) {
this.employees = employees;
this.count = employees.size();
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}

@XmlElement(name="employee")
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}

}




Listing 7. Define content negotiation

<bean class="org.springframework.web.servlet.view
.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml"/>
<entry key="html" value="text/html"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view
.BeanNameViewResolver"/>
<bean class="org.springframework.web.servlet.view
.UrlBasedViewResolver">
<property name="viewClass" value=
"org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
</bean>



Listing 8. employees.jsp in /WEB-INF/jsp

<table border=1>
<thead><tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr></thead>
<c:forEach var="employee" items="${employees.employees}">
<tr>
<td>${employee.id}</td>
<td>${employee.name}</td>
<td>${employee.email}</td>
</tr>
</c:forEach>
</table>



下面演示Clients如何与 REST services交互

curl –HAccept:application/xml http://localhost:8080/rest/service/employees

下面返回的xml包含employees



Figure 2. 用浏览器打开的HTML展示






下面演示创建一个新的employee到服务端,

curl -X POST -HContent-type:application/xml --data
"<employee><id>3</id><name>guest</name><email>guest@ibm.com</employee>" http://localhost:8080/rest/service/employee


这样一个新的employee注册好了. 可以用第一个例子的 employee 列表验证下.

PUT 和POST方法类似.

curl -X PUT -HContent-type:application/xml --data
"<employee><id>3</id><name>guest3</name><email>guest3@ibm.com</employee>" http://localhost:8080/rest/service/employee/3


上面代码更新了编号为3的 employee 数据。

现在spring3的mvc层以及完全支持REST了,你可以很轻松的用Spring APIs和注解去构建RESTful web services.

原文链接地址Build RESTful web services using Spring 3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: