基于REST的Web服务及基于Ajax的客户端

引言

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

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

  REST 不是一种协议,而是一种体系结构风格,这是非常重要的区别。

  对于 Web 服务,W3C 对 Web 服务的正式定义如下所示:

   “Web 服务是由 URI 标识的一个软件系统,并且使用 XML 对它的公共接口和绑定进行定义和描述。其他软件系统可以发现它的定义。然后,这些系统就可以按照 Web 服务预先确定的方式与它进行交互,并使用通过 Internet 协议传输的基于 XML 的消息。”

  常识告诉我们,Web 服务主要用于计算机与计算机之间的通信,而不是计算机与用户之间的通信。基于 REST 的 Web 服务是使用 REST 体系结构风格创建的 Web 服务,下一个部分中将通过一个示例来说明如何构建基于 REST 的 Web 服务。要掌握这一内容,您首先需要了解 Ajax,这是很重要的。(如果您是 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 操作。

   实现基于 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+" <input type='button' value='
GetEmpDetails' οnclick="+'"'+"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" οnclick="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 以显示特定雇员的详细信息。

   结束语

  在本文中,您了解了如何使用 Servlet 和基于 Ajax 的客户端来编写基于 REST 的 Web 服务。希望您能够发现,可以很容易地理解和实现基于 REST 的 Web 服务。请查看下面的参考资料部分中所提供的有价值的链接。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值