`

体验rails1.2的REST风格

阅读更多
    REST这个名词已经听过许久,在javaeye的ruby版上也看到不少的讨论,一开始是搞不明白的,似乎跟webservice有关。今天读了《RESTfull Rails Development》和几篇介绍REST的文章开始有点明白。REST 是英文 Representational State Transfer 的缩写,有中文翻译为“具象状态传输”。读这篇文章《学习REST》对于初次接触REST的人来说更好理解。

    我们在 Web 应用中处理来自客户端的请求时,通常只考虑 GET 和 POST 这两种 HTTP 请求方法。实际上,HTTP 还有 HEAD、PUT、DELETE 等请求方法。而在 REST 架构中,用不同的 HTTP 请求方法来处理对资源的 CRUD(创建、读取、更新和删除)操作:

  • POST: 创建
  • GET: 读取
  • PUT: 更新
  • DELETE: 删除

经过这样的一番扩展,我们对一个资源的 CRUD 操作就可以通过同一个 URI 完成了。需要注意的是REST的核心就是资源(resources)这个概念。我们所说的webservice是一种建立在http协议上的远程调用,而REST就是把远程调用抽象成对远程资源的CRUD的操作,正好可以用HTTP的PUT GET POST DELETE来对应,而不是重新发明一个协议(比如soap,简单对象访问协议)。REST与AJAX的流行,甚至远至设计模式的兴起,都充分说明一个现象,在成熟的应用的基础上创新而非扩展出复杂所谓“创新性”架构在软件行业是更为可靠。

    实战体验REST可以从IBM Developer的这篇文章开始《跨越边界:Rest On Rails》。这篇文章是在Rails1.2发布之前出来的,有些地方已经可以修改的更简练,我把我的练习过程记录下,并添加了C#调用REST风格web service的例子。

    首先,你的机器上需要安装rails1.2,并且假设你对rails有基本的了解,建立一个应用叫service,命令行执行:

  
<!----> rails service

rails自动帮你生成应用的基本结构和基础代码,然后编辑config下面的database.yml设置数据库,并建立数据service_development,我用的是mysql数据库。

create.bmp

利用rails1.2新的scaffold命令:

<!---->ruby script/generate scaffold_resource person

这个命令将自动生成ActiveRecord,Controller以及View,在\app\models下可以发现自动生成的Model——person.rb。打开service\db\migrate下面的001_create_people.rb,编辑如下:

<!---->class CreatePeople < ActiveRecord::Migration
  def self
.up
    create_table 
:people do |t|
     t
.column :first_name, :string, :limit => 40
     t
.column :last_name, :string, :limit => 40
     t
.column :email, :string, :limit => 40
     t
.column :phone, :string, :limit => 15
    end
  end

  def self
.down
    drop_table 
:people
  end
end

利用rake命令自动建表,执行
<!---->rake db:migrate
rails默认表明是Model的复数形式,也就是这里将自动建立一张名叫people的表。

OK,一切就绪,启动WEBric,访问http://localhost:3000/people,显示:
rest1.bmp

scaffold已经帮我们自动生成了一个对person资源的crud操作,增删改查似乎跟传统的rails没有什么不同嘛。如果你认真观察在操作过程中URL的变化情况就会发现在操作过程中URL的变化很小,而且与传统rails的URL路由相比,省去了action名称。出现的变化在/people、/people/1、/people/1;edit和/people/new这几个之中。在/people的URL中隐藏这可能是http的POST或者GET的方法,前者用于create操作,而GET用于show操作,具体你可以查看app/controllers/目录下的PeopleController类,每个action的前面都注释了它们将对应哪个HTTP方法。而/people/1中的1指的是资源的标志符,比如这里person的id,通过这个ID来进行资源的操作,也许是PUT方法(更新),也许是DELETE方法(删除)。rails实现PUT和Delete是通过隐藏字段来实现的,查看编辑页面生成的html源代码,你将发现一个_method的隐藏字段,值为PUT。而另外两个URL:/people/1;edit和/people/new,这两个并非严格意义上的RESTful URL,它们只是为了显示用,显示form表单用于新建和编辑。关于RESTful风格的URL的详细讨论请见《RESTfull Rails Development》文档。

    如果rails只是这样的威力,那就有点小提大做了,看看PeopleController的show action,它对应于http的GET请求,返回people列表:
<!----># GET /people/1
  # GET /people/1.xml

  def show
    
@person = Person.find(params[:id])

    respond_to 
do |format|
      
format.html # show.rhtml
      format.xml  { render :xml => @person.to_xml }
    end
  end

神奇的地方在respond_to方法中,根据请求文件类型(http Header的ContentType),显示html格式,或者xml格式(还有其他支持,比如json、RSS、Atom等等)。比如你添加了一个person,通过http://localhost:3000/people/1访问,可以看到这个人员的具体信息:
rest2.bmp
我们再通过http://localhost:3000/people/3.xml访问看到的却是一个xml文件:

rest3.bmp

不仅如此,我们也可以通过其他语言编写客户端来调用http://localhost:3000/people/1这个url,慢着,这不正是web service远程调用吗?没错,REST风格的web service相比于wsdl、soap定义的web service简单了太多太多,也更加实用。我们来编写一个java类调用http://localhost:3000/people获得所有的人员列表:
<!---->package example;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class RESTDemo {

    
/**
     * 
@param args
     
*/
    
public static void main(String[] args) {
        RESTDemo restDemo 
= new RESTDemo();
            restDemo.get();
        
    }

    
void get() {

        
try {
            URL url 
= new URL("http://localhost:3000/people");
            URLConnection urlConnection 
= url.openConnection();
            urlConnection.setRequestProperty(
"accept""text/xml");
            BufferedReader in 
= new BufferedReader(new InputStreamReader(
                    urlConnection.getInputStream()));
            String str;

            
while ((str = in.readLine()) != null) {
                System.out.println(str);
            }

            in.close();
        } 
catch (Exception e) {
            System.out.println(e);
        }
    }
}

我们没有什么服务端接口class,我们也不用生成什么stub,我们调用的最常见最常见的http协议,发送的是默认的GET请求,rails自动将该请求转发给show action。注意,我们这里把accept设置为text/xml,show方法根据此格式返回一个xml文档,下面是输出:
<!----><?xml version="1.0" encoding="UTF-8"?>
<people>
  
<person>
    
<email>killme2008@gmail.com</email>
    
<first-name>dennis</first-name>
    
<id type="integer">1</id>
    
<last-name>zane</last-name>
    
<phone>1355XXXXXXX</phone>
  
</person>
</people>

如果仅仅是GET请求是不够的,我们说过,把远程调用抽象成对远程资源的CRUD操作,那么如何create、delete和update远程资源呢?同样很简单,比如我们通过C#远程调用,创建一个新person,还记的我说过吗?/people可以是POST请求,他将调用PeopleController的create方法:
<!---->using System;
using System.Net;
using System.IO;
using System.Text;
namespace demo
{
    
class RESTDemo
    {
        
static void Main(string[] args)
        {
            
string xmlText = "<person> " + "<first-name>jordan</first-name>"
                    
+ "<last-name>jordan</last-name>"
                    
+ "<email>maggie@tate.com</email>"
                    
+ "<phone>010-XXXXXXXX</phone>" + "</person>";
            Uri address 
= new Uri("http://localhost:3000/people");  
   
            
// 创建web请求
            HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;  
   
            
// 设置请求类型为POST,调用create action
            request.Method = "POST";  
            request.ContentType 
= "application/xml";

            
byte[] xmlBytes = Encoding.ASCII.GetBytes(xmlText);

            
using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(xmlBytes, 
0, xmlBytes.Length);
            }
            
using (WebResponse wr = request.GetResponse())
            {
                wr.
                
//打印返回的http头
                Console.WriteLine(wr.Headers.ToString());
               
            }              
           

        }
    }
}

执行此程序,刷新http://localhost:3000/people,可以看到新建了一个人员如下

rest4.bmp

好极了,GET和POST都有了,那么PUT对应的更新和DELETE对应的删除又该怎么做呢,唯一的区别就是设置请求类型不同而已,java调用如下:
<!---->    void put() {
        
try {
            String xmlText 
= "<person> " + "<first-name>test</first-name>"
                    
+ "<last-name>test</last-name>"
                    
+ "<email>maggie@tate.com</email>"
                    
+ "<phone>010-XXXXXXXX</phone>" + "</person>";

            URL url 
= new URL("http://localhost:3000/people/1");
            HttpURLConnection conn 
= (HttpURLConnection) url.openConnection();
            conn.setDoOutput(
true);
            //设置请求为PUT
            conn.setRequestMethod(
"PUT");
            conn.setRequestProperty(
"Content-Type""text/xml");
            OutputStreamWriter wr 
= new OutputStreamWriter(conn
                    .getOutputStream());
            wr.write(xmlText);
            wr.flush();
            wr.close();
        } 
catch (Exception e) {
            System.out.println(
"Error" + e);
        }
    }

    
void delete() {
        
try {
            URL url 
= new URL("http://localhost:3000/people/2");
            HttpURLConnection conn 
= (HttpURLConnection) url.openConnection();
            conn.setDoOutput(
true);
            //设置请求为DELETE
            conn.setRequestMethod(
"DELETE");
            conn.setRequestProperty(
"Content-Type""text/xml");
            
if(conn.getResponseCode()==200)
                System.out.println(
"删除成功!");
        }
catch (Exception e) {
            System.out.println(
"Error" + e);
        }
    }

这里的put方法将第一个人员的名字改了,而delete方法干脆将刚才C#添加的人员删除掉。异构系统的远程调用变的如此简单很轻松,把什么EJB、CORBA、SOAP统统忘掉吧。想象这样的场景,所有的网站都提供REST风格的API,这个世界将是什么模样?

    REST带来的不仅仅是web service的改变,对MVC架构同样具有很重要的意义,过去我们的复用通常在MODEL层,我们一直希望复用业务逻辑层,却没有想过是否能复用Controller甚至View呢?REST为我们提供了可能,比如以一个很经常被提到的例子来说,用户加入某个圈子这个操作跟圈子的管理员将用户加入圈子的操作是一样,但是操作成功后的跳转显示的页面也许不同,过去也许我们是通过写两个不同的Action来实现,而现在,同一个Action(加入圈子这个操作)只负责发送数据(XML格式的文档),而页面的展示将留给客户端去选择,从而复用了Controller,减少了Action和View层的代码量。进一步,请你想象,REST与AJAX的技术结合产生多么有趣的画面。REST仅用于提供数据,展现更多的交给了客户端。

    本文仅仅是我接触REST这两天的学习总结,对于REST的应用才刚刚起步,需要更多的探讨和实践。其实java实现REST也是相当简单的,servlet本身就是很好的模型,恐怕没有多人注意到HttpServlet类中的doPut和doDelete方法,我们过去太强调GET和POST,反而忽视了PUT和DELETE可能带来的改变。java开源世界中已经有了REST风格的框架,比如cetia4,这是一个servlet-base的REST框架,值的关注。


dennis 2007-03-20 20:04 发表评论
分享到:
评论

相关推荐

    使用rails编写REST风格的web应用

    总结来说,"使用rails编写REST风格的web应用"涉及的内容包括Rails框架基础、MVC模式的理解、RESTful设计原则的应用、路由配置、控制器和模型的编写、视图渲染以及相关的测试和安全措施。学习这部分内容将使开发者...

    Rails上的API:使用Rails构建REST APIAPIs on Rails: Building REST APIs with Rails

    REST(Representational State Transfer)是一种软件架构风格,用于定义客户端与服务端之间交互的标准方式。RESTful API是基于HTTP协议设计的,通过不同的HTTP方法(如GET、POST、PUT和DELETE)来执行对应的操作,并...

    使用rails编写REST风格的web应用.pdf

    标题与描述均指向了"使用Rails编写REST风格的Web应用"这一主题,这是一份深入探讨如何运用Ruby on Rails框架来构建遵循REST(Representational State Transfer)架构风格的Web应用程序的指南。REST作为一种架构风格...

    Agile Web Development with Rails 2 Edition正式版

    一旦官方发布了Rails 1.2版本的Gem,用户可以卸载临时版本的Rails,并移除`vendor/rails`目录。 #### 四、Rails 1.2版本特性 尽管本书没有详细介绍Rails 1.2版本的具体特性,但从上下文中可以推测出此版本可能包括...

    Pragmatic - Agile Web Development with Rails 2nd

    本书撰写时,Rails的核心团队已创建了1.2版本的代码库,但尚未将其封装为Gem,这在当时对读者来说可能构成了一定的挑战,因为这意味着若要体验书中所提及的最新特性,需要安装所谓的Edge版本(即未正式发布的版本)...

    Agile Web Development with Rails 2nd Edition

    尽管本书并未详细列举Rails 1.2的所有新增特性,但从上下文可以推测出,1.2版本可能包括但不限于以下更新点: - **性能优化**:提高应用程序的响应速度和并发处理能力。 - **安全性增强**:加强了默认的安全设置,...

    跨越边界:REST on Rails

    Ruby on Rails是一个突然流行起来的框架,充当着Ruby编程语言的催化剂。随着Ruby的经验不断成功,开发人员开始寻求把他们的...本文介绍了如何在Ruby on Rails中添加REST风格的Web服务,并从Ruby和Java代码调用服务。

    RESTful Rails Development

    REST(Representational State Transfer)是一种软件架构风格,最初由 Roy Fielding 在他的博士论文中提出。它定义了一组构建服务的原则和约束条件,使得客户端和服务端可以通过 HTTP 协议进行交互。在 REST 风格的...

    用Ext Scaffold插件打造Rails的Ext风格

    标题中的“用Ext Scaffold插件打造Rails的Ext风格”指的是在Ruby on Rails(Rails)框架中,使用Ext JS库和一个名为“Ext Scaffold”的插件来创建图形用户界面(GUI)。Ext JS是一个流行的JavaScript库,提供了丰富...

    中文维基百科上的REST资料

    例如,Ruby on Rails 1.2以后的版本就支持RESTful模型。 在实现RESTful API时,通常会用到HTTP协议,URI用于指定资源,而对资源的操作则映射到HTTP协议提供的各种方法。资源的表现形式可以是XML或者HTML,也可以是...

    rails_rest_vote:RESTful投票宝典,用于Rails应用

    Rails Rest Vote是一个Ruby Gem,可为任何模型的Rails应用程序添加投票功能,并公开其RESTful API。 如果您在Web应用程序中以及移动应用程序中使用了诸如angular2之类的任何前端客户端,那将非常有帮助。 先决条件...

    Rails101_by_rails4.0

    RESTful是一种软件架构风格,指导开发者如何设计能够遵循REST原则的应用接口。通过RESTful的学习,读者可以构建出具有良好数据交互特性的Web服务。 《Rails101_by_rails4.0》通过 Lean Publishing 的出版流程,让...

    The Rails 4 Way

    - **REST简介**:REST(Representational State Transfer)是一种用于构建网络应用程序的架构风格,强调资源的概念及其表示。 - **Rails中的REST实现**:Rails默认遵循REST原则,通过资源路由和标准的控制器动作支持...

    Rails 101 入门电子书

    - 实现RESTful风格的接口。 - **代码示例**: - 创建GroupsController类。 - 实现每个动作的方法。 #### 八、补充章节:RESTful on Rails - **深入理解RESTful**: - RESTful API的设计原则。 - 如何在Rails中...

Global site tag (gtag.js) - Google Analytics