体验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数据库。

利用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,显示:

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访问,可以看到这个人员的具体信息:

我们再通过http://localhost:3000/people/3.xml访问看到的却是一个xml文件:

不仅如此,我们也可以通过其他语言编写客户端来调用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,可以看到新建了一个人员如下

好极了,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框架,值的关注。

文章转自庄周梦蝶  ,原文发布时间5.17

时间: 2024-10-03 06:57:19

体验rails1.2的REST风格的相关文章

《认知设计:提升学习体验的艺术》——学习风格

学习风格等等,什么是"听觉型.视觉型.触觉型.动觉型.概念型.社会型"的学习者?难道我们还需要知道学习者的学习风格?也许你对学习风格有一定了解.例如,你可能听过某人被描述为"视觉型学习者".这些分类是信奉学习风格的倡导者所提出的,他们觉得如果我们能够找出学习者的学习方式差异,我们就能够针对学习者的学习风格提供最适合他们的学习体验,并且提升学习效果.对学习风格有很多研究,下面是一些较为著名的结论: 加德纳(Gardner)多元智能-霍华·加德纳(Howard Gard

WPS Office 2012界面风格切换 想换就换

  金山办公软件已经正式发布了WPS Office 2012办公软件.可能有些用户还不适应WPS 2012版的新界面,现在就让小编给大家介绍下如何更改界面风格吧. WPS Office 2012遵循Windows 7主流设计风格的2012新界面,赋予你焕然一新的视觉享受.WPS 2012充分尊重用户的选择与喜好,提供双界面切换,用户可以无障碍的在新界面与经典界面之间转换,选择符合自己使用习惯.提高工作效率的界面风格与交互模式.让老用户得以保留长期积累的习惯和认知,同时能以最小学习成本去适应和接受

WPS Office 2012界面风格如何切换

  有些用户反映说还不适应WPS 2012版的新界面,没有关系,你也可以自己更改界面风格,具体步骤可以看下面详解. WPS Office 2012遵循Windows 7主流设计风格的2012新界面,赋予你焕然一新的视觉享受.WPS 2012充分尊重用户的选择与喜好,提供双界面切换,用户可以无障碍的在新界面与经典界面之间转换,选择符合自己使用习惯.提高工作效率的界面风格与交互模式.让老用户得以保留长期积累的习惯和认知,同时能以最小学习成本去适应和接受新的界面与体验. 经典风格界面 2012风格界面

一个页面重构工程师眼中的“用户体验”

中介交易 SEO诊断 淘宝客 云主机 技术大厅 在工业化设计融入人们生活的现今,用户体验一词就常常出现在人们的视线里,随着互联网web2.0时代的到来,大大小小的网站设计中也都开始关注用户体验的方面,对什么是用户体验(百度这四个字,比我写什么解释都好)就不做详细赘述了,相信大家比我了解的更加丰富. 用户体验从产品设计阶段便开始介入进来,如原型设计中交互模式设计.功能实现方式设计都融入了设计人员对用户的关怀,听过这样的一句话:"具有良好用户体验的产品,不仅仅取决于一个有着丰富交互设计经验的产品设计

天樽与墨迹天气再次联手,推出风格简洁明朗的墨迹皮肤

前期天樽携手墨迹天气推出的"空气健康小贴士"大受好评,即时发布的空气质量信息和温馨的健康提醒让用户倍感亲切,日前,海尔天樽与墨迹天气再次联手,推出一款风格简洁明朗的墨迹皮肤,再次获得用户赞赏.通过墨迹天气皮肤的"皮肤小铺"栏目即可轻松找到这款皮肤.需要说明的是,这款皮肤目前是免费下载,用户只需点击安装,待下载完成后即可体验.整款皮肤风格简洁明快,各项数据布局清晰.在实时显示的窗口部件上,汇集了时间.日期.温度.天气.空气质量等相关指标,用户可以第一时间获取相关信息.

云OS 2.7系统新功能体验

在刚刚过去的2013年,智能手机发展迅猛,无论是硬件配置方面的提升,还是软件方面的革新,都得到了高速发展.其中,阿里巴巴于去年4月发布云OS 2.0版本,之后又进行了多次更新,用户体验也得到了不断提升,而日前则正式发布了云OS 2.7版本,相比之前的版本得到了全面的飞跃,接下来大家可跟随笔者的图片和文字,共同体验一番. 简约的风格,便捷的体验 在界面风格方面,云OS 2.7进行了多项革新,使得手机的界面风格更加简约.轻盈,而且更具质感与品味,视觉体验也更加舒服,看到它的第一眼,笔者心中就油然生出

Chrono&Cash:另类复古风格街机游戏

与Stardash和Meganoid类似,Chrono&Cash也是一款来自OrangePixel的复古风格游戏,现在已经登录谷歌Play Store.让我们来体验一下这款像素风格低清晰度游戏的另一种乐趣.游戏主角是一个名叫Cash的天才小偷,以及他的超时空机器人CR2.二人组队通过时间旅行来从坏人手中盗取各式各样的宝藏,游戏的方式简单而巧妙.游戏的画面依然保持着OrangePixel的像素化风格,虽然分辨率低不过色彩鲜艳悦目.Chrono&Cash游戏截图Chrono&Cash游

交互设计实例分析:如何学习开心网的设计

开心网最开始的特点是转贴与投票,以及其本身朴素的界面设计.后来许多模仿都仿造其开发相同的功能与设计,不过依然无法超越开心网本身,那么后来者该如何学习开心网? 1.开心模型 齐白石有句话,叫"学我者生,似我者死".放在开心上也是成立的. 我一直在想这个问题,既然学开心者生,那从何学起?如何学来?想了很长时间,大概有如下的5点总结. 首先保持产品本身的封闭性,只允许用户通过"邀请机制"加入,保障新用户的质量与存活率. 其次,在创始初期推出分量十足的社交游戏,一大数小,制

分享外贸网站优化那点事

由于互联网的迅速发展,网购已经成为市民朋友们不可缺少的一部分了,国内的市场经营的很好以后,就会想着要去经营国外市场,自从经济危机以后,外贸站的营销也是越来越难做,那对于一个外贸公司来说,要怎么去优化外贸站? 首先:竟然是做一个外贸站,域名,空间都是你需要去考虑的,域名最好是简单明了的,最好是跟的网站的关键词搭上关系,同时也要注意到你网站用户的体验,是国外的用户,最好是用英文,这样更容易让人记住.空间的选择要考虑到速度问题,国外对时间的观念是很强的,人家不愿意把时间花在等你的网站打开.外贸站的空间