当这套 REST API 不能满足用户的需求时,需要增加
新的 REST Web Service。本文将介绍如何在不修改现有代码的
前提下,向 IBM ">SmartCloud Entry 中添加定制的 REST Web Service。
IBM SmartCloud Entry 并非从一砖一瓦开始构造自己的 REST Web Service,而是借助了一些工具。在正式开始之前,您需要对下列名词有一定的了解。
REST: 全称是 Representational state transfer。它是一种 Web 服务的 风格,与作为传统 Web 服务(以 SOAP 为基础)相比,具有轻量化、易于构建、无状态以及使用 HTTP 协议等优势。 JAX-RS:全称是Java TM API for RESTful Web Services,是一个 Java 编程语言的应用程序接口。它提供了对创建 REST 风格的 Web Service 的支持。借助从 Java SE 5 开始引入的标注(Annotation ),JAX-RS 可以简化部署 Web Service 的过程。 Restlet:诞生于 2005 年,是一个针对 Java 语言开发人员的开源项目。Restlet 旨在以一种简单的方式,向开发人员提供各个应用场景下实现 REST Web Service 的方法。虽然早在 JAX-RS 诞生前,Restlet 已经存在了,
但是 Restlet 仍然提供了对 JAX-RS 的支持。目前 Restlet 的最新
稳定版本是 2.1.1,本文的所有内容都是基于 Restlet 2.1.1 来进行说明。 OSGi:全称是 Open Services
Gateway initiative,一直都被视为一种成熟的模块化系统框架,它一般包括桌面应用程序、Web 应用程序、移动应用程序,以及中间件。 它提供了一种底层的基础设施,可用来开发具有模块化、动态性的面向服务应用程序。
Restlet 实现 JAX-RS
在 Restlet 2.1.1 中,可以将 Restlet 分成两个部分:
REST 应用开发 Core:包含 Restlet API 和 Restlet Engine Extension:包含 Restlet 对支持各个技术的扩展,如
Servlet 和 JAX-RS
如果您对 Restlet 稍有了解,可以知道仅靠 Restlet 的 Core 部分就能够实现 REST Web API。而 IBM SmartCloud Entry 则用 JAX-RS 来定义 REST 资源,之后借助 Restlet 对 JAX-RS 的扩展来关联 Restlet Engine 和 REST 资源,从而实现 REST Web API。对于这两种方式的优劣,在这里不做赘述,您可以从网上找到说明。接下来将简要介绍 IBM SmartCloud Entry 的实现方式。
清单 1. 将 JAX-RS application 与 Restlet 关联
package com.developerworks.rest.test;import org.restlet.Component;import org.restlet.ext.jaxrs.JaxRs
Application;import javax.ws.rs.core.Application;public class TestComponent extends Component { public static Application jaxRsApplication; public TestComponent() { super(); // 创造 JAX-RS runtime final JaxRsApplication application = new JaxRsApplication(getContext().createChildContext()); // 将一个 JAX-RS application 添加到 JAX-RS runtime application.add(jaxRsApplication); // 将 JAX-RS runtime 必须添加到一个 Component 中 getDefaultHost().attach(application); }}
清单 1 展示了如何用 Restlet 对 JAX-RS 的扩展来关联 Restlet 和 JAX-RS application。
将 REST Web API 部署到 Servlet 容器中
IBM SmartCloud Entry 是以 OSGi 为核心框架开构建的,所使用的 Servlet 容器是 OSGi 内嵌的 Jetty。清单 2 展示了如何将一个 Restlet Component 部署到 Servlet 容器中,这里我们用到了 Restlet 对 Servlet 的扩展。
清单 2. 将 Restlet Component 部署到 Servlet 容器中
package com.developerworks.rest.test;import java.util.Properties;import javax.ws.rs.ext.RuntimeDelegate;import org.osgi.service.http.HttpContext;import org.osgi.service.http.HttpService;import org.restlet.engine.Engine;import org.restlet.ext.jaxrs.internal.spi.RuntimeDelegateImpl;import org.restlet.ext.servlet.ServerServlet;public class TestApiWhiteboard { static { Engine.getInstance().setUserClassLoader(TestComponent.class.getClassLoader()); } private HttpService http; // 调用该函数启动 REST Web Service public void startup() { ServerServlet serverServlet = new ServerServlet(); Properties initParams = new Properties(); initParams.put("org.restlet.component", TestComponent.class.getName()); HttpContext httpContext = http.createDefaultHttpContext(); try { http.registerServlet("/test", serverServlet, initParams, httpContext); } catch (Exception e) { e.printStackTrace(); } } public void shutdown() { http.unregister("/test"); }}
清单 2 将之前实现的 Component 作为参数传递给 ServerServlet,再将 ServerServlet 注册进 Servlet 容器。至此,我们已经能够发布 REST Web Service 了,但是等等,我们的 Web Service 空空如也,我们还没有添加 REST 资源。