运用 REST API 集成及扩展 IBM Rational Team Concert

IBM Rational Team Concert 简介

IBM Rational Team Concert (RTC) 是构建在 IBM Rational 面向软件交付技术的下一代协作平台 Jazz 平台上的第一个商用产品、一个协作式的软件开发环境,它包含了集成的源代码控制、工作项管理和构建管理等功能。IBM Rational Team Concert 是一个可实时相互协作的软件交付环境,可以帮助跨地域分布的开发团队简化协作开发过程,并使其软件交付过程实现自动化管理。developerWorks 及网络上有大量的文章对 RTC 进行介绍,这里就不再赘述。参考资源部分列出了一些资源供大家学习。截至本文发表 RTC 最新的稳定版是 2.0.0.2,因此,以下所有对于 RTC REST API 的介绍都是基于 2.0.0.2 的。

RTC REST API 的实现遵守 OSLC-CM 规范。

什么是 OSLC?

OSLC 是 Open Service for Lifecycle Collaboration 的缩写,亦即面向生命周期协作的开放服务。OSLC 社区的成立旨在帮助软件实施团队在合作中简化生命周期工具的使用。OSLC 社区的使命是创建开放、公开的资源和接口描述用以分享软件实施团队所依赖的基础设施,例如,变更管理、测试用例、缺陷、需求以及用户故事。倘若所有对生命周期资源和服务的访问都遵从公共的规范,工具之间传统的障碍将自然消除从而开启一扇通向新型协作方式的大门。无论是对于最敏捷的或者是最传统的项目,OSLC 都能够为软件实施团队以及工具提供商带来价值,同样,它也能够造福于商业工具、开源工具以及内部开发的工具。

什么是 OSLC-CM?

OSLC-CM 是 OSLC 的一个子集。它的重点在于变更管理(Change Management)。通过 OSLC-CM 你可以查询、链接、获取、创建以及更新变更请求。

RTC 1.0 仅提供给用户 Java API 以集成和扩展 RTC。Java API 包含两部分:Eclipse 插件 API 和一般 Java API。Eclipse 插件 API 适用于在现有的 RTC Eclipse 客户端中扩展 RTC 应用而一般 Java API 则适用于普通的 Java 应用程序。在 RTC 1.0.1 中,出现了 REST API,不过是实验版。在 RTC 2.0 中,RTC 正式开始支持 REST API,目前 REST API 支持的功能还较为有限,但对于一般的集成需求已经足够,其功能主要集中在对工作项(Work Item)的管理。在后续的版本中,越来越多的功能将会加入到 REST API 中。目前已经有不少软件在使用 RTC REST API,例如 Mylyn、Rational Quality Manager、Rational Requirements Composer 以及 Git Integration 等。

关于 REST 的优点,维基百科上是这样定义的:

  • 可以利用缓存 Cache 来提高响应速度
  • 通讯本身的无状态性可以让不同的服务器的处理一系列请求中的不同请求,提高服务器的扩展性
  • 浏览器即可作为客户端,简化软件需求
  • 相对与其他叠加在 HTTP 协议之上的机制,REST 的软件依赖性更小
  • 不需要额外的资源发现机制
  • 在软件技术演进中的长期的兼容性更好

对 RTC 而言,有了 REST API 的支持后,客户端的程序语言将不再局限于 Java。即便你的应用是一般的 Java 应用,REST API 同样值得推荐,因为使用 REST API 代码更加简洁并且依赖的 Jar 文件比较少(使用 Java API 约需要引入大约 20M 的 Jar 文件,但是使用 REST API 大约只需要引入 3M 左右的 Jar 文件,见本文提供的示例程序)。

简单来说,RTC REST API 提供了如下功能:

  • 以多种格式(如 JSON、XML、ATOM 以及 HTML)在不同粒度级别上获取工作项
  • 通过更新 JSON 或者 XML 的方式修改工作项的属性
  • 通过获取 HTML 的创建对话框模块来创建工作项
  • 通过发送带有 JSON 或者 XML 格式数据的 Post 请求创建工作项
  • 增加或者删除链接
  • 通过全文检索和指定属性查询工作项
  • 通过获取 HTML 的选择器模块查询工作项

下面对 RTC REST API 的功能做更为具体的介绍。

服务发现

RTC 提供了服务发现机制。用户应当通过该机制获得需要的服务 URL 而不是将服务 URL 硬编码在自己的程序中。根服务发现 URL 格式如下:

https://://rootservices

实例如:

https://localhost:9443/jazz/rootservices

该 URL 将返回一个 XML 文档,其中对主要的服务资源入口做了定义。该机制是一个链式机制,也就是说,当你获得了根服务描述文档后,可以根据其中包含的资源的 URL 进一步获取子集中的服务 URL。

获取资源表象

通过如下两种 URL 格式可以获取资源表象。

格式一(位置 URI)

https://:/jazz/resource/itemName/
com.ibm.team.workitem.WorkItem/

实例如:

https://localhost:9443/jazz/resource/itemName/
com.ibm.team.workitem.WorkItem/262

以及

https://localhost:9443/jazz/resource/itemOid/
com.ibm.team.workitem.WorkItem/_Kk8YQFElEd6wrL4Qi7w25Q

格式二:

https://:/jazz/oslc/workitems/
.

实例如:

https://localhost:9443/jazz/oslc/workitems/821.xml

以及

https://localhost:9443/jazz/oslc/workitems/_Kk8YQFElEd6wrL4Qi7w25Q.json

此此格式主要用于开发阶段。

除了 .xml 和 .json,其他几种支持的媒体类型扩展包括:.hover.html,.atom 以及 .xhtml。如若要返回一个资源的多种表象则需要通过指定 HTTP 的 Accept 头信息或者在 URL 中指定 _mediaType 参数,例如:

https://localhost:9443/jazz/resource/itemName/
com.ibm.team.workitem.WorkItem/821?_mediaType=application/x-oslc-cm-changerequest%2Bjson

该 URL 将返回工作项 821 的 JSON 格式数据。

获取资源表象部分属性

有时我们只需要获取一个资源部分属性数据,尤其在移动设备应用中,出于减少带宽消耗的考虑,我们通常只获取我们真正需要的数据。通过在 URL 中添加 oslc_cm.properties=propA,propB 可以实现资源部分属性数据的获取。例如:

https://localhost:9443/jazz/oslc/workitems/
821.json?oslc_cm.properties=dc:identifier,dc:title

将仅返回资源的 dc:identifierdc:title 属性值。

查询工作项

查询工作项通过在 https://:/jazz/oslc/contexts//workitems 的后面添加 ?oslc_cm.query=[query] 语句实现。[query] 是一个 CM Query 语句。详细语法请参见 变更管理查询语法讲解

例如,下面这个查询是一个编码过的全文检索查询,用来获取所有包含“NPE”文本的工作项。

https://localhost:9443/jazz/oslc/contexts/_9BHm0EqVEd6HXO10niqZpg/workitems
?oslc_cm.query=oslc_cm%3AsearchTerms%3D%22NPE%22

同样,你可以通过添加 oslc_cm.properties 语句限制结果返回的属性值,并且还可以使用“/sort”指定查询返回结果的排序方式。分页查询也是支持的,例如使用 oslc_cm.pageSize 参数就可以指定查询结果每页返回的条目数。

使用预定义的查询语句

通过形如 https://localhost:9443/jazz/oslc/queries.xml(当然你可以用 queries.json)的 URL 可以获得所有预定义的查询语句。增加 oslc_cm.query 参数则可以根据指定的查询参数过滤返回的查询语句结果。获取查询语句的唯一标识符之后,便可进而通过如下的 URL 获取该查询的返回结果。

https://localhost:9443/jazz/oslc/queries/_vS4rsF5eEd6EzYK1TPZjDw/rtc_cm:results.atom

创建工作项

构造并发送包含某种媒体类型(例如 JSON)的工作项表象数据的 POST 请求到形如下的 URL 即可创建一个工作项:

https://localhost:9443/jazz/oslc/contexts/_9BHm0EqVEd6HXO10niqZpg/workitems

其中,_9BHm0EqVEd6HXO10niqZpg 是项目区域唯一标识符。那么,如何得知媒体类型的具体格式规范呢?当然,你可以通过查看 OSLC-CM 规范获得。但是,一个更为直观快捷的方式是你先用那种媒体类型获得某个工作项的数据,然后查看其格式。例如,你可以通过以下的 URL 返回的数据得知如何定义一个工作项的 JSON 格式表象。

https://localhost:9443/jazz/oslc/workitems/821.json

创建草稿工作项同创建一般的工作项一样,只需将发送的目标 URL 改为如下:

https://localhost:9443/jazz/oslc/contexts/_9BHm0EqVEd6HXO10niqZpg/drafts/workitems

更新工作项

更新工作项的过程为:首先以某种媒体格式获取资源数据,接着根据需要对数据进行修改,最后发送 PUT 或者 PATCH 请求。可能会出现在你获取资源并且提交修期间其他客户端也修改了该资源的情况,如果没有采取任何措施,那么你的提交就会覆盖先前那个客户端的修改内容,从而造成数据丢失。为防止此现象的发生,你可以在获取资源后获取并保存它的 ETag 属性值,并在发送 PUT 或者 PATCH 请求的 If-Match 头信息中设置该 ETag 值。那么,倘若其他客户端在期间做了修改,你将会收到 HTTP 响应的 412 返回代码。此时,你应该重新获取数据并修改后重新提交。

更新工作项的部分属性

有时我们需要更新工作项的部分属性(或许这样更加安全)。你可以通过以下两种方式:

方法一:发送 URL 中带有 oslc_cm.properties 的 PUT 请求

例如,发送 PUT 请求到:

https://localhost:9443/jazz/resource/
itemName/com.ibm.team.workitem.WorkItem/821?oslc_cm.properties=dc:type

无论发送的数据中包含多少更改,都只更新 dc:type 属性。

方法二:发送 PATCH 请求

例如,发送仅包含 dc:type 属性的数据的 PATCH 请求到:

https://localhost:9443/jazz/oslc/workitems/821

也将只更改其 dc:type 属性。

增加 / 删除链接

通过在发送的工作项表象数据中包含链接更新整个工作项是一增加链接的方式,除此以外,你还可以采用发送包含如下的 JSON 或者 XML 数据的 POST 请求到形如:

https://localhost:9443/jazz/oslc/workitems/
821/oslc_cm:relatedChangeManagement

的 URL 的方式。

XML


JSON

{
 "rdf:resource":"https:\/\/example.org\/changerequests\/10253",
 "oslc_cm:label":"Task 10253"
}

如需增加多条链接,只需在 JSON 或 XML 数据中增加多项即可。

删除链接如同增加链接一样:从数据中删除链接后,发送 PUT 或者 PATCH 请求更新工作项。

增加备注

发送带有如下数据的 POST 请求到形如 https://localhost:9443/jazz/oslc/workitems/821/rtc_cm:comments 的 URL 可以为工作项增加备注。

{
 "dc:description":"My new comment"
}

上面的例子是 JSON 数据。当然,你也可以采用其他的媒体类型。

通常,为了方便其他程序模块对 REST API 的调用,我们都会将其封装。这样的程序模块叫做 REST API 客户端。本文提供了一个 Java 实现的 REST API 客户端示例程序供用户参考。当然,该示例程序纯粹用于向读者示范 RTC REST API 的使用,所以它对 RTC REST API 封装的并不完整并且可能存有缺陷,为了简单起见,其中资源 URL 也并非从 RTC 服务发现功能中获取。因此,读者若真要在自己的环境中使用,仍需要进一步修改和完善它。该示例程序简单的封装了对 RTC REST API 的调用,并实现了如下步骤的测试用例:

  1. 创建一个标题为“Sample title”的缺陷
  2. 通过缺陷的 ID 获取该新创建的缺陷
  3. 修改缺陷的严重性以及标题值
  4. 为缺陷增加备注
  5. 将缺陷的状态从 New 改为 Resolved 再改为 Closed
  6. 通过缺陷的状态及标题查询出该缺陷

开发环境的搭建

下载代码包 RTCRestClient_sample.zip,(参见下载)并直接作为已有项目导入到工作区。出于种种考虑,本文附带的代码包并未包含依赖的 Jar 文件,因此你会发现项目有编译错误,所以接下来你需要自己下载依赖的 Jar 文件并手动添加到项目构建路径当中。


图 1. 导入示例项目
图 1. 导入示例项目

以下是该示例程序依赖的开源项目:

  • HttpClient 4.0.1:用来发送处理 HTTP 请求以调用 RTC REST API。
  • Json-lib 2.3 :示例程序中选用了 JSON 的发送 / 返回数据格式。Json-lib 用来封装发送及返回的数据。
  • Log4j-1.2.12:用来输出日志。
  • 若干 Apache Commons 项目:这些都是 HttpClient 以及 Json-lib 依赖的库文件。

以下是你需要下载及导入的 Jar 文件:

  • apache-mime4j-0.6.jar
  • commons-beanutils-1.8.3.jar
  • commons-codec-1.3.jar
  • commons-collections-3.2.1.jar
  • httpclient-4.0.1.jar
  • httpcore-4.0.1.jar
  • httpmime-4.0.1.jar
  • commons-lang-2.5.jar
  • commons-logging-1.1.1.jar
  • ezmorph-1.0.6.jar
  • json-lib-2.3-jdk15.jar
  • log4j-1.2.12.jar

你可以从以下网站获得上面的 Jar 文件:

运行示例程序

如果项目能够正常编译之后,你就可以开始运行示例程序。下面是运行该示例程序的步骤:

步骤一:在 config.properties 中设置你的 RTC 的用户名,密码,RTC 基本 URL 以及项目区域名称。


清单 1. config.properties 设置
# RTC account id, e.g shenrui@cn.ibm.com
username=shenrui@cn.ibm.com
# RTC account password
password=
# RTC base URL, e.g. https://:/jazz
rtc.base.url=
# Project Area name, e.g. Mashup Center
projectarea.name=Mashup Center

步骤二:运行 SampleCaller.java。由于示例程序中使用 JVM 的断言语句,所以,请在运行配置中添加 JVM 参数“-ea”以启用 JVM 的断言功能。


图 2. 示例程序运行设置
图 2. 示例程序运行设置

如果一些正常,Eclipse 控制台将显示如下类似信息。


清单 2. 控制台输出示例
2010-06-03 13:33:37 [com.ibm.rtc.restclient.SampleCaller]-[INFO] 
    14789 was created successfully. -(:40)
2010-06-03 13:33:44 [com.ibm.rtc.restclient.SampleCaller]-[INFO] 
    14789 was retrived successfully. -(:47)
2010-06-03 13:34:01 [com.ibm.rtc.restclient.SampleCaller]-[INFO] 
    14789 was updated successfully. -(:59)
2010-06-03 13:34:20 [com.ibm.rtc.restclient.SampleCaller]-[INFO] 
    14789 was closed successfully. -(:72)
2010-06-03 13:34:31 [com.ibm.rtc.restclient.SampleCaller]-[INFO] 
    14789 was searched successfully. -(:84)

示例程序源代码解析

打开包管理器,所有类如下图所示。


图 3. 源代码包结构
图 3. 源代码包结构

下面对每个类的功能进行简单地介绍。

RTCRestClientException.java 该类作为该项目的根 Exception 类。 Resource.java 该类封装了 RTC 中常规资源的属性:包含资源的名称、类型以及对应的资源 URL。比如工作项中的 Severity、Priority 以及 State 等都是一个资源对象实例。 Workitem.java 该类对 RTC 中的工作项进行了封装。一个工作项中通常包含唯一标识符、标题、描述、Severity、Priority 等属性。该类也包含了同 JSON 对象之间相互转换的方法。 Configuration.java 该类用于读取系统配置文件 config.properties。 QueryResults.java 该类用以封装 REST API 的查询结果。 RTCRestClient.java 该类封装了对 RTC REST API 调用,以传统的 Java 方法暴露对 RTC 的操作。对于每次 REST API 操作,程序会检查是否已进行过认证或者之前认证后获取的 Cookie 是否仍有效或者已过期。如果 Cookie 已过期则重新认证。本示例代码实现是表单认证方式,如果你的 RTC 配置的是基本认证方式则需要自己对代码做些修改。 WorkitemManager.java 该类通过对 RTCRestClient.java 的调用封装了若干对工作项的操作,例如创建工作项、查询工作项、修改工作项状态等操作。 SampleCaller.java 该类是一个示例客户端调用程序。它调用了 WorkitemManager 中的方法并输出运行结果。

创建工作项代码详解


图 4. UML 时序图(创建工作项)
图 4. UML 时序图(创建工作项)

从上面的时序图中,读者可以清楚地了解代码之间的调用关系。下面是相关的代码片断。


清单 3. SampleCaller.java
Workitem wi=new Workitem();
wi.setTitle(title);
wi.setDescription("Sample description");
wi.setFiledAgainst(new Resource(Resource.RES_TYPE_FILEDAGAINST,"MM V2.4"));
wi.setFoundIn(new Resource(Resource.RES_TYPE_FOUNDIN,"2.4/CSA2"));
wi.setSeverity(new Resource(Resource.RES_TYPE_SEVERITY,"Sev4"));
wi.setPriority(new Resource(Resource.RES_TYPE_PRIORITY,"Low"));
wi.setOwnedBy(RTCRestClient.getInstance().getUser("example@example.com"));
wi.setType(new Resource(Resource.RES_TYPE_TYPE,"Defect"));
wi=manager.createWorkitem(wi);

首先,创建一个 Workitem 实例,然后构造并设置需要的属性,之后调用 WorkitemManager.java 的 createWorkitem 方法创建工作项。


清单 4. WorkitemManager.java
public Workitem createWorkitem(Workitem workitem){
    JSON jsonObject=client.post(projectAreaWorkitemsUrl, workitem.toJSONString());
    return Workitem.fromJSON((JSONObject) jsonObject);
}

createWorkitem 方法调用 RTCRestClient.java 的 post 方法发送 POST 请求以创建 Workitem,之后并调用 Workitem.java 的 fromJSON 方法将返回的字符串构造成一个 Workitem 实例作为方法返回值。


清单 5. RTCRestClient.java
public JSON post(String url, String requestContent) {
        return jsonHttp(url, HTTP_METHOD_POST, requestContent);
    }
private JSON jsonHttp(String url, int httpType, String requestContent) {
try {
    authenticate();
    DefaultHttpClient httpClient = new DefaultHttpClient();
    httpClient.getCookieStore().addCookie(cookie);
    HttpRequestBase httpMethod = null;
    switch (httpType) {
        case HTTP_METHOD_GET:
            httpMethod = new HttpGet(url);
            break;
        case HTTP_METHOD_POST:
            httpMethod = new HttpPost(url);
            break;
        case HTTP_METHOD_PUT:
            httpMethod = new HttpPut(url);
            break;
        }
        httpMethod.addHeader("Content-Type","application/x-oslc-cm-change-request+json");
        httpMethod.addHeader("Accept", "text/json");
        if (httpType == HTTP_METHOD_POST || httpType == HTTP_METHOD_PUT) {
            StringEntity requestEntity = new StringEntity(requestContent);
                ((HttpEntityEnclosingRequestBase) httpMethod)
                        .setEntity(requestEntity);
        }
        HttpResponse response = httpClient.execute(httpMethod);
        String rtJson = convertStreamToString(response.getEntity()
                    .getContent());
        httpClient.getConnectionManager().shutdown();
        return JSONSerializer.toJSON(rtJson);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

jsonHttp 对各种类型的 HTTP 请求进行了封装并将返回值构造成 JSON 对象。而 post,get 以及 put 方法都调用 jsonHttp 方法实现真正的 HTTP 请求操作,只是传入了不同的 HTTP 请求类型字符串 httpType。HTTP_METHOD_GET,HTTP_METHOD_POST 以及 HTTP_METHOD_PUT 是三个字符串静态常量,用来代表不同的 HTTP 请求类型。

清单 6. Workitem.java

public static Workitem fromJSON(JSONObject jsonObject) {
    DynaBean bean = (DynaBean) JSONSerializer.toJava(jsonObject);
    Workitem workitem=new Workitem();
    workitem.setIdentifier(((Integer) bean.get("dc:identifier")).intValue());
    workitem.setTitle((String) bean.get("dc:title"));
    workitem.setDescription((String) bean.get("dc:description"));
    workitem.setType(createResource(bean,"dc:type",Resource.RES_TYPE_TYPE));
    workitem.setOwnedBy(createResource(bean,"rtc_cm:ownedBy",
        Resource.RES_TYPE_USER));
    workitem.setFoundIn(createResource(bean,"rtc_cm:foundIn",
        Resource.RES_TYPE_FOUNDIN));
    workitem.setFiledAgainst(createResource(bean,"rtc_cm:filedAgainst",
        Resource.RES_TYPE_FILEDAGAINST));
    workitem.setSeverity(createResource(bean,"oslc_cm:severity",
        Resource.RES_TYPE_SEVERITY));
    workitem.setPriority(createResource(bean,"oslc_cm:priority",
        Resource.RES_TYPE_PRIORITY));
    workitem.setState(createResource(bean,"rtc_cm:state",Resource.RES_TYPE_STATE));
    return workitem;
}

fromJSON 方法能够将 JSONObject 对象转换成一个 Workitem 实例。

更新工作项代码详解


图 5. UML 时序图(创建工作项)
图 5. UML 时序图(创建工作项)

更新工作项的过程比创建工作项的过程稍微复杂一些。下面是相关的代码片断。


清单 7. SampleCaller.java
/*
* Get the workitem
*/
wi=manager.getWorkitemById(wi.getIdentifier());
assert wi.getIdentifier()==workitemId;
logger.info(wi.getIdentifier()+" was retrived successfully.");
/*
* Change its severity
*/
Resource severity=wi.getSeverity();
severity.setTitle("Sev3");
wi.setSeverity(severity);
wi.setTitle(newTitle);
wi=manager.updateWorkitem(wi);
assert "Sev3".equals(wi.getSeverity().getTitle());
assert newTitle.equals(wi.getTitle());
logger.info(wi.getIdentifier()+" was updated successfully.");

SampleCaller 首先通过唯一标识符调用 WorkitemManager.java 的 getWorkitemById 方法获取 Workitem 实例,然后修改 Workitem 实例的属性值,最后调用 WorkitemManager.java 的 updateWorkitem 方法更新 Workitem 实例。


清单 8. WorkitemManager.java
public Workitem updateWorkitem(Workitem workitem){
    String url=workitemsUrl+"/"+workitem.getIdentifier();
    JSON jsonObject=client.put(url, workitem.toJSONString());
    return Workitem.fromJSON((JSONObject) jsonObject);
}
public Workitem getWorkitemById(int id){
    String url=workitemsUrl+"/"+id;
    return Workitem.fromJSON((JSONObject) client.get(url));
}

WorkitemManager.java 调用 RTCRestCient.java 的 put 方法更新 Workitem 数据,其中的 workitemsUrl 在 WorkitemManager.java 的构造函数被初始化,代码如下:


清单 9. WorkitemManager.java 构造函数
private WorkitemManager(){
    client=RTCRestClient.getInstance();
    String projectAreaId=client.getProjectAreaId();
    String rtcBaseUrl=client.getRtcBaseURL();
    projectAreaWorkitemsUrl= rtcBaseUrl + "/oslc/contexts/" 
        + projectAreaId + "/workitems";
    workitemsUrl= rtcBaseUrl + "/oslc/workitems";
}

workitemUrl 理论上应当通过服务发现机制获得,这里只是从简单实现角度出发,所以采用了字符串拼接的方法。


清单 10. RTCRestClient.java
public JSON get(String url) {
    return jsonHttp(url, HTTP_METHOD_GET, null);
}

public JSON put(String url, String requestContent) {
    return jsonHttp(url, HTTP_METHOD_PUT, requestContent);
}

如“创建工作项详解”部分所述:get 和 put 方法都调用 jsonHttp 方法实现真正的 HTTP 请求操作的。

值得一提的是目前无法通过像修改工作项的其他属性那样的方式修改工作项的状态,而需要发送带有 _action 参数的 PUT 请求实现。例如,要关闭一个工作项,那么需要发送 PUT 请求到

https://localhost:9443/jazz/oslc/workitems/821?_action=bugzillaWorkflow.action.close

不过,action 字符串是可以配置的,因此本示例中的这个 action 字符串未必可以适用于你的 RTC,所以关于该 action 字符串请联系你的 RTC 管理员。如果你需要你在关闭工作项的同时又修改某些工作项属性,可以在发送的 PUT 请求中数据中包含修改后的属性值(当然,你需要把它构造成 JSON,XML 或者其他支持的媒体类型)。如果你不需要修改任何属性,就在 PUT 请求中包含唯一标识符。你可以在 WorkitemManager.java 的 changeState 方法中找到相关的代码。

另外,通过 RTCRestClient.java 的 getResUrlByTitle 方法,对于所有的资源,你只需要指定名称就可以获得资源对应的 URL 后构造出 Resource 实例。但是不幸地是在目前的版本中,你无法通过用户的名称查询出对应的资源 URL(会出现一个 dc:title 无法被识别的错误信息),所以该示例程序实现了 getUser(String userId) 方法从而通过用户唯一标识符获取对应的用户实例。

本文对涉及 RTC REST API 的相关概念以及其提供的功能做了介绍。但是限于篇幅原因,有些内容并未展开(例如,OSLC-CM 查询语法),所以建议读者在阅读完本文后对于未展开讲解的部分自己学习。另外,本文虽然附有 RTC REST API 客户端的示例代码,但是它仅仅为读者提供参考,所以,无论从功能的完整性以及整体程序架构上说,它都很不完善。读者如果需要在自己的程序中集成 RTC,仍需要在参考示范代码的基础上进一步修改和完善。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14780873/viewspace-671757/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/14780873/viewspace-671757/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值