`
j2ee_zhongqi
  • 浏览: 202617 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

REST与Web2.0(三):基于 REST 的 Web 服务及其基于 Ajax 的客户端

阅读更多
from:http://www.ibm.com/developerworks/cn/webservices/ws-restajax/

简介:
基于 REST 的 Web 服务是使用 REpresentational State Transfer (REST) 体系结构风格构建的 Web 服务。本文介绍了一种编写基于 REST 的 Web 服务的方法,其中使用一个简单的代理 Servlet 和基于 Asynchronous XML + JavaScript (Ajax) 的客户端。


引言

在 Roy Fielding 的论文中,他将 REST 作为目前 Web 体系结构的一种基础概念进行了详细介绍,他为 REST 提出了下列标准:

为现代 Web 体系结构进行建模的一组约束。
REST 原则已应用于 HTTP 和 URI 规范。
在 HTTP 的发展过程中是可见的

REST 不是一种协议,而是一种体系结构风格,这是非常重要的区别
常识告诉我们,Web 服务主要用于计算机与计算机之间的通信,而不是计算机与用户之间的通信。基于 REST 的 Web 服务是使用 REST 体系结构风格创建的 Web 服务,下一个部分中将通过一个示例来说明如何构建基于 REST 的 Web 服务。要掌握这一内容,您首先需要了解 Ajax,这是很重要的.

创建基于 REST 的 Web 服务
要创建基于 REST 的 Web 服务,您首先需要确定希望作为 Web 服务进行公开的所有资源。一些资源的示例包括雇员列表、雇员详细信息、订购单,等等。在 REST 中,每种资源都是通过唯一的统一资源标识符(Uniform Resource Identifier,URI)来标识的。您需要为每种资源确定唯一的 URI。例如,雇员列表可以标识如下:http://www.employee-details.com/employees-list。雇员详细信息可以使用如下所示的 URI 进行标识:http://www.employee-details.com/employees/01234。

使用 HTTP 操作 GET、PUT、POST 和 DELETE 以检索和修改您的资源。在您的资源表示中提供一些超链接,以提供更多的相关信息。为这些资源的请求和响应数据指定格式,这需要 PUT 和 POST 操作。

图 1 中的关系图显示了与一个基于 REST 的 Web 服务之间的交互。


实现基于 REST 的 Web 服务
您可以使用 HTTP Servlet 来实现基于 REST 的 Web 服务。本文使用一个虚拟的服务演示了实现的过程,而这个服务提供了有关公司雇员的详细信息。雇员列表资源使用一个逻辑 URI 进行表示,http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee-list。当通过 HTTP GET 调用这个服务时,它将返回如清单 1 中所示的雇员列表

清单 1. 使用 HTTP GET 调用雇员列表
  
            <?xml version='1.0' encoding='UTF-8'?>
<p:Employees xmlns:p='http://www.employee-details.com'>
                <Employee id='00345'  href='/employees/00345'/>
	    <Employee id='00346'  href='/employees/00346'/>
                <Employee id='00347'  href='/employees/00347'/>
                <Employee id='00348'  href='/employees/00348'/>
</p:Employees>


类似地,雇员详细信息可以使用一个逻辑 URI 进行表示,如 http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee/0124。当通过 HTTP GET 调用这个服务时,它将返回如清单 2 中所示的雇员详细信息。


清单 2. 使用 HTTP GET 调用雇员详细信息
       
    <?xml version='1.0' encoding='UTF-8'?>
< EmpDetail xmlns:p='http://www.employee-details.com'>
                <<Emp-ID>00345</Emp-ID>
	    <Name>David Henry</Name>
               <Department>Finance</ Department >
</p:EmpDetail>

清单 3 显示了这个 Servlet 的代码。其中,所有操作都采用了硬编码方式,但是可以很容易地将其扩展为与数据库进行交互,以便成为一个实时的、基于 REST 的服务。


清单 3. Servlet 代码:
public class RESTDemoServlet extends HttpServlet implements Servlet {
 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#HttpServlet()
  */
 Map map =new HashMap();
	
 /* (non-Javadoc)
  * @see javax.servlet.GenericServlet#init()
  */
 public void init() throws ServletException {
  // TODO Auto-generated method stub
  super.init();
		
  Employee emp0 =new Employee("David","Finance");
  Employee emp1 =new Employee("Smith","HealthCare");
  Employee emp2 =new Employee("Adam","Information technology");
  Employee emp3 =new Employee("Stephan","Life Sciences");
		
  map.put("00345",emp0);
  map.put("00346",emp1);
  map.put("00347",emp2);
  map.put("00348",emp3);
 }
	
 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#doGet
      (HttpServletRequest arg0, HttpServletResponse arg1)
  */
 protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1) 
      throws ServletException, IOException {
  // TODO Auto-generated method stub
  arg1.setContentType("text/xml");
  PrintWriter out=arg1.getWriter();
  System.out.println(map);
  if(arg0.getPathInfo()!= null){
  String EmpId=arg0.getPathInfo().substring(1,arg0.getPathInfo().length());
  System.out.println(EmpId);
		
  out.write("<?xml version='1.0' encoding='UTF-8'? >"+"\n");
   out.write("<p:EmpDetail xmlns:p='http://www.employee-details.com' >"+"\n");
   out.write("<Emp-ID>"+EmpId+" </Emp-ID >"+"\n");
   out.write("<Name>"+((Employee)map.get(EmpId)).name+" </Name >"+"\n");
   out.write("<Department >"+((Employee)map.get(EmpId)).dept+" </Department >"+"\n");
   out.write("</p:EmpDetail >"+"\n");
   out.flush();
  }else{
   out.write("<?xml version='1.0' encoding='UTF-8'? >"+"\n");
   out.write("<p:Employees xmlns:p='http://www.employee-details.com' >"+"\n");
   out.write("<Employee id='00345' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00345'/ >"+"\n");
   out.write("<Employee id='00346' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00346'/ >"+"\n");
   out.write("<Employee id='00347' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00347'/ >"+"\n");
   out.write("<Employee id='00348' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00348'/ >"+"\n");
   out.write("</p:Employees >");
   out.flush();
  }
 }

 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#doPost
      (HttpServletRequest arg0, HttpServletResponse arg1)
  */
 protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) 
      throws ServletException, IOException {
  // TODO Auto-generated method stub
 }

	
}


在下一个部分中,了解如何为这个基于 REST 的 Web 服务编写 Ajax 客户端。
为基于 REST 的 Web 服务编写 Ajax 客户端
如前所述,Ajax 表示 Asynchronous JavaScript + XML。它有时也称为 XML HTTP 技术。在 Ajax 中,核心的技术主要是围绕实现与服务器的异步通信,而无需页面刷新。XMLHTTPRequest 对象支持对服务器进行异步 GET、POST、PUT 和 DELETE。这并不向用户显示任何内容,换句话说,不会显示状态消息。您可以为状态更改指定一个处理程序方法,并且当发生如下请求时将通知这个处理程序:

初始化
启动
在返回的过程中
完全完成
清单 4 显示了一个基于 Ajax 的 HTML 页面的代码,它可以用作上述基于 REST 的 Web 服务的客户端:
清单 4. 基于 Ajax 的 HTML 页面的代码
<SCRIPT language="javascript" type="text/javascript" >
var req=null;
//This function initializes XHR
function initXHR() {
 if (navigator.appName.indexOf("Microsoft") > -1 ) {
   try{
      req=new ActiveXObject("Microsoft.XMLHTTP");
     }catch(e1){
      alert("failed to create XHR in IE");
     }
   }else{
       try{
            req=new XMLHttpRequest();
           }catch(error){
            alert("failed to create XHR in FireFox");
           }
        }
}
//get an employee detail
function getEmpDetails(Empurl){
 initXHR();
 req.open("GET",Empurl, true);
 req.onreadystatechange=handleEmpDetailResponse;
 req.send(null);

}

//get employee list
function getEmployeeList(listurl){
 initXHR();
  req.open("GET", listurl, true);
  req.onreadystatechange=handleEmpListResponse;
  req.send(null);
}
function handleEmpDetailResponse(){
 //if Response is complete

  if(req.readyState==4){
   //response is OK
    if(req.status==200){
     var str="";
	var response=req.responseXML;
	var root=response.documentElement;
	for(i=0;i <root.childNodes.length;i++){
    	 if(root.childNodes[i].nodeType != 1) continue;
        var name=root.childNodes[i].nodeName;
        var value=root.childNodes[i].firstChild.nodeValue;
        str=str+name+"--- >"+value+" <br >";
  		}
	 document.getElementById("emp-div").style.display="";
	 document.getElementById("emp-detail-div").innerHTML=str;
	}else{
      document.getElementById("messageDiv").innerHTML=" <SPAN style='color:#FF0000; 
          font-size:12pt; text-decoration:none;' <Invalid URL or PartId </SPAN >";
	}
	req.abort();
   }
}

function handleEmpListResponse(){
 //if Response is complete

  if(req.readyState==4){
   //response is OK
    if(req.status==200){
     var pstr="";
     var response=req.responseXML;
     var root=response.documentElement;
     for(i=0;i <root.childNodes.length;i++){
      if(root.childNodes[i].nodeType != 1) continue;
       var id=root.childNodes[i].getAttribute("id");
       var href=root.childNodes[i].getAttribute("href");
         pstr=pstr+"EmpId"+"--- >"+id+"&nbsp; <input type='button' value='
            GetEmpDetails' onclick="+'"'+"getEmpDetails('"+href+"')"+'"'+">"+" <br >";
  	   }
	 document.getElementById("emp-list-div").style.display="";
	 document.getElementById("emp-list").innerHTML=pstr;
	}else{
	 document.getElementById("messageDiv").innerHTML=" <SPAN style='color:#FF0000; 
          font-size:12pt; text-decoration:none;' >Invalid Employee ID. </SPAN >";
	}
    }
}
</SCRIPT >
<center >
<input type="button" value="getEmployee-List" onclick="getEmployeeList
    'http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee-list')" > <br > <br >
<div id="messageDiv" > </div >
<div id="emp-list-div" style='color:#FF0000; font-size:12pt; text-decoration:none; 
      display:none;' >Employee List : </div > <br >
<div id="emp-list" > </div > <br > <br >
<div id="emp-div" style='color:#FF0000; font-size:12pt; text-decoration:none; 
      display:none;' >Selected Employee Detail : </div > <br >
<div id="emp-detail-div" > </div >
</center >


在清单 4 中,当用户单击 getEmployee-List 按钮时,会向服务器发送一个 XML HTTP 请求。为 XML HTTP 请求指定使用处理程序函数 handleEmpListResponse 来处理 readyState 更改。当服务器完成了响应(readyState = 4)并且该响应为 OK 时,您可以解析 XML 并将其添加到页面的文档对象模型(Document Object Model,DOM)后面,以显示雇员列表。类似地,当用户单击 GetEmpDetails 按钮时,处理程序函数 handleEmpDetailResponse 将处理来自服务器的 XML 响应,并修改页面的 DOM 以显示特定雇员的详细信息


  • 大小: 11.9 KB
分享到:
评论

相关推荐

    将SOA经验应用于Web 2.0实现

    使用SOAP和WSDL来构建不仅会使得你的项目时间变得更长,它们更不会带来任何益处……尽管REST简化了对某些类型服务的构建——特别是那些对外、面向Internet或Ajax客户端的服务,但仍然还有许多服务会通过应用SOAP,...

    Ajax模式与最佳实践(英文清晰版)

    AJAX三剑客之最佳实“剑”,深邃洞查Web开发整体架构,全面涵盖客户端与服务器端开发。磨亮您的Web 2.0开发利剑。 亲爱的读者:Ajax将我们带进了下一代Web应用。Ajax通过将客户端与服务器解耦,打破和客户端与服务器...

    pintura:Pintura是基于JSGI的RESTful JSONJavaScript服务器中间件堆栈,为Persevere 2.0框架提供了Web界面

    是一个跨平台的服务器端基于JavaScript的REST体系结构Web框架,它使用基于标准的HTTP客户端/服务器交互,并着重于JSON格式的数据。 Pintura为您提供了数据的RESTful HTTP / JSON接口,您可以简单地创建数据模型,而...

    PHP和MySQL Web开发第4版pdf以及源码

    第三篇 电子商务与安全性 第14章 运营一个电子商务网站 14.1 我们要实现什么目标 14.2 考虑电子商务网站的类型 14.2.1 使用在线说明书公布信息 14.2.2 接收产品或服务的订单 14.2.3 提供服务和数字产品 14.2.4...

    PHP和MySQL WEB开发(第4版)

    第三篇 电子商务与安全性 第14章 运营一个电子商务网站 14.1 我们要实现什么目标 14.2 考虑电子商务网站的类型 14.2.1 使用在线说明书公布信息 14.2.2 接收产品或服务的订单 14.2.3 提供服务和数字产品 14.2.4 为...

    ASP EXCEL导入SQL

     服务主要是指平台的核心服务,核心服务分为业务共通服务以及平台共通服务,平台共通服务是指与业务无关且是平台最基础的服务,如任务调度、消息队列、邮件服务、图片处  理、工作流引擎等;而业务共通服务指基于...

    PHP和MySQL Web开发第4版

    第三篇 电子商务与安全性 第14章 运营一个电子商务网站 14.1 我们要实现什么目标 14.2 考虑电子商务网站的类型 14.2.1 使用在线说明书公布信息 14.2.2 接收产品或服务的订单 14.2.3 提供服务和数字产品 14.2.4...

    Microsoft .NET Framework 3.5 Service Pack 1

    ADO.NET Data Services Framework 由满足以下条件的模式和库组合而成:支持将数据公开为一项基于 REST(具象状态传输)的灵活数据服务,企业网络内部或整个 Internet 上的 Web 客户端都可以使用该服务。ADO.NET Data...

    JAVA上百实例源码以及开源项目

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    intercooler-js:使AJAX像锚标签一样容易

    htmx 中冷器2.0(重命名为htmx 1.0)已发布。 它更小,更具表达力,并且不再依赖jQuery。 您可以在此处查看新网站: ... 这些功能使您可以使用简单直观的REST-ful架构构建现代化的Web应用程序,而

    Microsoft .NET Framework 4

    WCF 数据服务是 .NET Framework 的一个组件,可以利用此服务创建基于 REST 的服务和应用程序,以便使用开放式数据协议 (OData) 在 Web 上公开和使用数据。 WCF 数据服务具有多项新功能,包括增强的 BLOB 支持、数据...

    JAVA上百实例源码以及开源项目源代码

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    java开源包1

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    framword4.5

    WCF 数据服务是 .NET Framework 的一个组件,可以利用此服务创建基于 REST 的服务和应用程序,以便使用开放式数据协议 (OData) 在 Web 上公开和使用数据。 WCF 数据服务具有多项新功能,包括增强的 BLOB 支持、数据...

    java开源包11

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包2

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包3

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包6

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

    java开源包5

    JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor ...

Global site tag (gtag.js) - Google Analytics