Spring Social Evernote 简介

工程 | Josh Long | 2015年6月15日 | ...

这篇文章是由社区成员Tadayasu Tsuyukubo (@ttddyy)撰写的客座文章,他是 Spring Social Slideshare 项目的创建者。感谢 Tadaya!我希望看到更多这样的客座文章,所以——像往常一样——随时联系我!——Josh

Spring Social EvernoteSpring Social 生态系统中的一个社区模块。它是一个针对 Evernote 的服务提供商实现。它允许开发人员使用惯用的 Spring 习惯用法与 Evernote Java SDK 进行交互。

Evernote 采用了一种独特的方法向开发人员提供其 API。他们基于 Thrift 序列化格式 创建了 特定语言的 SDK。Evernote 的 CTO Dave Engberg 在 这篇博客文章中解释了选择 Thrift 的原因

Java SDK 包含 Thrift 生成的域类(例如NotebookNoteUser 等)和端点访问客户端(例如UserStoreClientNoteStoreClient 等)。即使~StoreClient 类很好地封装了身份验证和 Thrift 端点通信协议,它们仍然有一些限制。

例如,各种~StoreClient 类型中进行通信的所有 Thrift 方法都会抛出**受检**异常。此外,~StoreClient 类没有与其操作相对应的接口,这使得单元测试(稍微)有些困难。Spring Social Evernote 填补了这些空白,同时提供了一个熟悉的 Spring Social 编程模型。

功能

Spring Social Evernote 提供了一个熟悉的基于 Spring 和 Java 的编程模型,该模型使用接口、非受检异常和针对 Thrift 基于域对象的空安全Collection。它还提供了一个 Evernote OAuth API 的服务提供商实现。

Evernote 接口及其实现EvernoteTemplate是 API 的核心类型。Evernote 接口返回与 SDK 的~StoreClient 类相对应的~StoreOperations(例如NoteStoreOperationsUserStoreOperations)接口。这些接口上的方法抛出**非受检**EvernoteException,而不是受检EDAM*Exception。这些实现还对 Thrift 生成的域类型中的集合具有更智能的空值处理。

Evernote evernote = new EvernoteTemplate(
    EvernoteService.SANDBOX, "your-custom-access-token");

// interface based programming
NoteStoreOperations noteStore = evernote.noteStoreOperations();

// no checked exception is thrown
Notebook notebook = noteStore.getDefaultNotebook();

// no NPE when there are no shared notebooks
for (SharedNotebook sharedNotebook : notebook.getSharedNotebooks()) {  
    ...
}

基于接口的 Store 客户端编程

~StoreClientOperations 接口类对应于~StoreClient 实现类(例如,NoteStoreClientOperations 对应于com.evernote.clients.NoteStoreClient)。

// NoteStoreOperations is interface encapsulating NoteStoreClient
NoteStoreOperations noteStore = evernote.noteStoreClientOperations();
Notebook notebook = noteStore.getNotebook("...");

端点操作的非受检异常

EDAM 异常(例如com.evernote.edam.error.EDAMUserException)和 Thrift 异常(例如com.evernote.Thrift.TException)会被捕获并重新抛出为类型为EvernoteException的*运行时*异常。

// with UserStoreOperations, no explicit exception handling is required
User user = evernote.userStoreOperations().getUser();

// or explicitly you can get exception info
try {
  User user = userStoreClient.getUser();
} catch(EvernoteException e) {
  if (e.isEDAMUserException()) {
     EDAMErrorCode errorCode = e.getEDAMErrorCode();
     EDAMUserException originalException = e.getCause();
     ....
  }
}

Thrift 基于域对象的空安全集合处理

在 Thrift 中,空集合不会被序列化,但是这种约定会导致在使用 API 时出现一些意外的NullPointerException。Spring Social Evernote 实现使用空集合来清理这些值。

Note note = evernote.noteStoreOperations().getNote(...)
// it is safe to loop without null check
for(Resource resource: note.getResources()) {
  ...
}

或者(在 Java 8 中)

 evernote.noteStoreOperations()
    .getNote()
    .getResources()
        .forEach ( r -> System.out.println( r.toString() ));

Spring Social Evernote 会检查类型的脏数据并还原其空值,前提是集合在序列化之前为空。

有关此特定支持的更多信息,请查看nullsafe-Thrift——一个概念验证项目。

Evernote OAuth 的服务提供商实现

注册ConnectionFactory

要将 Evernote 环境(sandboxprodyinxiang)注册到 Spring Social 服务提供商连接框架中,您可以使用特定于环境的ConnectionFactory 类,例如EvernoteSandboxConnectionFactoryEvernoteProductionConnectionFactoryEvernoteYinXiangConnectionFactory。或者,您可以在构造函数中将EvernoteService 枚举传递给EvernoteConnectionFactory

ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();

// sandbox connection
registry.addConnectionFactory(new EvernoteSandboxConnectionFactory("consumerKey", "consumerSecret"));

// production connection
registry.addConnectionFactory(new EvernoteProductionConnectionFactory("consumerKey", "consumerSecret"));

// or by EvernoteService enum
registry.addConnectionFactory(new EvernoteConnectionFactory("consumerKey", "consumerSecret", EvernoteService.SANDBOX));

使用 Evernote 的 OAuth API

执行基于 Evernote 的 OAuth 身份验证 的过程如下:

// obtain request token (temporal credential)
OAuth1Operations oauthOperations = evernoteConnectionFactory.getOAuthOperations();
OAuthToken requestToken = oauthOperations.fetchRequestToken(
    callbackUrl, null);

// construct authorization url with callback url for client to redirect
OAuth1Parameters parameters = new OAuth1Parameters();
parameters.set("preferRegistration", "true"); // create account
parameters.set("supportLinkedSandbox", "true");

String authorizeUrl = oauthOperations.buildAuthorizeUrl(
        requestToken.getValue(), parameters);

// obtain access token
OAuthToken requestToken = new OAuthToken(oauthToken, requestTokenSecret);
AuthorizedRequestToken authorizedRequestToken = new AuthorizedRequestToken(requestToken, oauthVerifier);

OAuth1Operations oAuth1Operations = evernoteConnectionFactory.getOAuthOperations(); // EvernoteOAuth1Operations
EvernoteOAuthToken accessToken = (EvernoteOAuthToken)oAuth1Operations.exchangeForAccessToken(authorizedRequestToken, null);

后续步骤

有关更多项目文档,请查看项目 Wiki 页面。此外,还可以在此测试类中演示 Thrift 中的空安全集合。

由于 Evernote 没有 RESTful API,我创建了一个 Web 应用程序Evernote Rest Webapp,它为 Evernote 服务提供 RESTful 端点。它构建在Spring BootSpring Social Evernote之上。如果您感兴趣,此实现可以作为一种桥接 API。

总结

Spring Social Evernote 提供了现代化的编程模型,并可轻松将 Evernote 身份验证集成到您的应用程序中。

如果您有任何建议、问题或其他任何事项,请通过 @ttddyy 联系我。

获取 Spring Newsletter

通过 Spring Newsletter 保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring在一个简单的订阅中提供对OpenJDK™、Spring和Apache Tomcat®的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部