引入 Spring Social Evernote

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

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

Spring Social EvernoteSpring Social 生态系统中的一个社区模块。它是 Evernote 的一个服务提供商实现。它允许开发者使用符合 Spring 习惯用法的方式使用 Evernote Java SDK

Evernote 在向开发者提供 API 方面采取了独特的方法。他们基于 Thrift 序列化格式 创建了特定语言的 SDK。Evernote 首席技术官 Dave Engberg 在这篇博客中解释了选择 Thrift 的动机

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

例如,各种 ~StoreClient 类型中执行通信的所有 Thrift 方法都会抛出受检异常。此外,~StoreClient 类没有与其操作对应的接口,这在一定程度上阻碍了单元测试。Spring Social Evernote 弥补了这些不足,同时提供了熟悉的 Spring Social 编程模型。

特性

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

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

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 中,null 集合不会被序列化,但这种约定在使用 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 会进行类型脏检查,并在序列化之前恢复它们的 null 值。

关于此特定支持的更多信息,请参阅 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 邮件列表

通过 Spring 邮件列表保持联系

订阅

提升自我

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

了解更多

获得支持

Tanzu Spring 提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅即可获得。

了解更多

即将到来的活动

查看 Spring 社区所有即将到来的活动。

查看全部