社交化 Spring 应用程序

工程 | Craig Walls | 2010年11月3日 | ...

越来越多的网民正在使用互联网通过社交网站与朋友、家人和同事联系。曾经通过电子邮件进行的对话现在正在人们的 Facebook 墙上用简短的消息进行,或者在 Twitter 上用简短的推文进行。曾经通过握手建立的联系现在使用 LinkedIn 建立。当需要面对面会议时,可以使用 TripIt 分享旅行细节。

正如人们正在使用这些社交网站相互互动一样,企业也正在寻找方法将自己融入社交图谱,以便能够以更个性化的方式与客户联系,并将他们的网站扩展为客户社交体验的一部分。

本周,我们高兴地发布了 Spring Social 的第一个里程碑版本,这是一个 Spring 的新扩展,旨在提供一个平台,在这个平台上可以构建支持社交功能的 Spring 应用程序。我想借此机会向您介绍 Spring Social,并让您体验一下它提供的功能。

安全地共享社交数据

从表面上看,开发与各种社交网络交互的应用程序似乎很简单。由于大多数社交网络都提供 REST API,因此 Spring 的 RestTemplate 似乎是您所需要的一切。但是您会很快发现,这些社交 REST API 受 OAuth 保护,并且使用 OAuth 凭据对通过 RestTemplate 发送的请求进行签名是一项非平凡的任务。

OAuth 是一种开放协议,它允许用户与另一个应用程序共享其托管在一个或多个服务提供商上的数据。通过访问这些数据,应用程序可以以超越服务提供商本身曾经设想或想象的方式聚合、呈现和处理信息。

几乎所有主要的提供商都支持 OAuth,包括 Twitter、Facebook、LinkedIn、TripIt 和 Foursquare,以及 Google 和 Yahoo API。因此,OAuth 对于开发支持社交功能的应用程序至关重要。

OAuth 安全交互的开始是一个来回对话,通常称为“OAuth 舞蹈”。在典型的 OAuth 舞蹈中,涉及三个参与方

  • 服务提供商(例如 Twitter 或 LinkedIn)
  • 想要访问或更新由该服务提供商托管数据的用户。
  • 用户想要与其共享数据的消费者应用程序。

此舞蹈中的关键步骤如下

  1. 消费者应用程序将用户定向到服务提供商的站点以登录并授权消费者。
  2. 假设用户同意授予消费者访问其数据的权限,则流程将发送回消费者应用程序。
  3. 消费者应用程序从服务提供商接收访问令牌。

步骤 3 中收到的访问令牌是必须随对服务提供商的 REST API 的任何请求一起发送的“代客钥匙”。在 OAuth 1 中,这意味着访问令牌以及请求 URL、参数和一些其他信息被收集到一个基本字符串中,加密后在请求中以 Authorization 标头发送。构建此标头并将其附加到请求是一项复杂的任务。这就是使用 RestTemplate 访问 OAuth 保护的资源很困难的原因。如果您弄错了,服务提供商将对您尝试访问的任何资源返回 HTTP 401,并且调试加密的 Authorization 标头很棘手。

使用社交模板

Spring Social 的一个关键组件是其社交模板集合。这些模板(在幕后利用 RestTemplate)公开其建模的服务提供商的操作,为您处理添加 OAuth Authorization 标头的复杂性。

Spring Social 1.0.0.M1 包括 4 个可供选择的社交模板

  • TwitterTemplate
  • FacebookTemplate
  • LinkedInTemplate
  • TripItTemplate

要使用这些模板中的任何一个,只需创建一个实例,通过构造函数参数提供 OAuth 连接详细信息。例如,要创建 TwitterTemplate 的实例

TwitterTemplate twitter = new TwitterTemplate(apiKey, apiSecret, accessToken, accessTokenSecret);

TwitterTemplate 构造函数的四个参数都是字符串值。当您向 Twitter 注册应用程序时,会为您提供 API 密钥和 API 密钥(请参阅 http://dev.twitter.com/apps/new)。访问令牌和访问令牌密钥在与 Twitter 的 OAuth 舞蹈结束时按用户授予您的应用程序。在这一点上,我将假设您已经获得了所有这四个值;稍后我们将回到如何管理 API 密钥和令牌。

创建其他社交模板的实例没有什么不同。LinkedInTemplateTripItTemplate 各自具有与上面显示的 TwitterTemplate 构造函数相同的参数列表的构造函数。由于 Facebook 的 API 安全性基于 OAuth 2,因此 FacebookTemplate 具有稍微简单的构造函数,只需要访问令牌的值。

FacebookTemplate facebook = new FacebookTemplate(accessToken);

一旦您拥有其中一个社交模板的实例,您可以用它做什么?如果您使用的是 TwitterTemplate,您可能想知道已认证用户的 Twitter 屏幕名称

String screenName = twitter.getProfileId();

或者对于更复杂的事情,也许您可以代表用户发送推文

twitter.updateStatus("Hey, I'm tweeting with #Spring Social!");

同样,使用 FacebookTemplate,您可以发布到用户的墙上

facebook.updateStatus("Spring Social can also post to Facebook!");

如果您想检查用户的即将到来的旅行行程,TripItTemplategetTrips() 可以满足您的要求

List trips = tripIt.getTrips();
for(Trip trip : trips) {
    System.out.println("I'm traveling to " + trip.getPrimaryLocation() +
                                 " on " + trip.getStartDate());
}

这只是您可以使用 Spring Social 模板执行的操作示例。查看 API 文档以查看其他可用操作。

管理 OAuth 连接

当我创建上面的 TwitterTemplate 实例时,我忽略了 API 密钥/密钥和访问令牌的来源。最初,访问令牌将在用户授权应用程序访问其托管在服务提供商上的数据后接收。但是您可能不想强制用户每次使用您的应用程序时都执行授权,因此您需要一种方法来长期存储访问令牌以便在将来的会话中重复使用。

在其第一个里程碑版本中,Spring Social 没有提供 OAuth 令牌管理策略,而是让应用程序自行获取和管理 OAuth 详细信息。这是我们打算在 1.0 里程碑 2 中解决的问题。但是,与此同时,我们可以参考 Greenhouse 来了解这可能如何实现。

在 Greenhouse 中,关于服务提供商的所有信息都存储在关系数据库中的 ServiceProvider 表中,该表具有以下模式

如您所见,ServiceProvider 表包含提供商的 API 密钥和密钥等内容。为了访问单个服务提供商记录,Greenhouse 使用 JdbcServiceProviderFactory,这是 ServiceProvider 接口的实现

package com.springsource.greenhouse.connect;

public interface ServiceProviderFactory {

    ServiceProvider getServiceProvider(String name);

    <S> ServiceProvider<S> getServiceProvider(String name, Class<S> serviceType);

}

要从数据库中检索 Twitter 服务提供商,Greenhouse 只需调用 getServiceProvider() 方法,并将“twitter”(提供商的名称)作为参数传递。对于 Twitter,这最终会返回 TwitterServiceProvider 的实例,它是 ServiceProvider 接口的实现。

ServiceProvider 具有多种方法,但其中两种方法对于令牌管理很有趣。第一个是 connect(),Greenhouse 使用它来创建其用户与其在服务提供商上的社交身份之间的连接

void connect(Long accountId, AuthorizedRequestToken requestToken);

在调用 connect() 方法时,Greenhouse 已经完成了足够的 OAuth 舞蹈以获得授权的请求令牌。将这些与用户的帐户 ID 一起传递将创建 AccountConnection 表中的连接。AccountConnection 表具有以下模式

建立连接后,您可以使用 ServiceProvidergetServiceOperations() 方法来获取 TwitterOperations 的实例(TwitterTemplate 基于此接口)

TwitterOperations twitter = twitterProvider.getServiceOperations(accountId);

getServiceOperations() 的内部,ServiceProvider 实现检索访问令牌,并将其与自己的 API 密钥和密钥一起使用来构造 TwitterTemplate,从而使应用程序无需直接处理访问令牌。

在 Greenhouse 中,TwitterOperations 实例是请求范围的 bean,通过 ServiceProvidersApiConfiguration 中的工厂方法创建,使用 Spring JavaConfig,如下所示

@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public TwitterOperations twitter(ServiceProvider<TwitterOperations> twitterProvider, @Value("#{request.getAttribute('account')}") Account account) {

    return twitterProvider.getServiceOperations(accountId(account));

}

作为 Spring bean,TwitterOperations 可以注入到任何需要与 Twitter 交换数据的其他 Spring bean 中。例如,在 Greenhouse 中,EventsController 是处理所有面向事件的请求的 Web 交互的 Spring MVC 控制器。它使用 TwitterOperations 代表用户发布有关事件的推文。它通过其构造函数注入 TwitterOperations bean。


@Inject
public EventsController(EventRepository eventRepository, TwitterOperations twitterApi) {
    this.eventRepository = eventRepository;
    this.twitterApi = twitterApi;
}

正如我提到的,我们打算在里程碑 2 中将 ServiceProvider 功能从 Greenhouse 转移到 Spring Social。显然,当前的实现支持 OAuth 详细信息的关系存储,但我们渴望听到您关于在其他类型的存储中维护 OAuth 信息的其他实现的想法。

运行 Greenhouse

尽管您可以在 http://greenhouse.springsource.org 查看正在运行的 Greenhouse 应用程序,但您可能希望签出 Greenhouse 源代码并自行尝试,以便在您探索 Spring Social 时进行探索。为此,请按照以下步骤操作

  1. 签出 Greenhouse 源代码
    git clone git://git.springsource.org/greenhouse/greenhouse.git
  2. 将 Greenhouse 项目导入 SpringSource Tool Suite
  3. 将 Greenhouse 项目拖到 SpringSource tcServer(在“服务器”选项卡下)中以部署应用程序。
  4. 编辑 tcServer 的运行配置,将“-DspringProfiles=embedded”添加到 VM 参数列表的末尾。
  5. 启动服务器并在 Web 浏览器中访问 https://127.0.0.1:8080/greenhouse。

步骤 4 是必需的,因为 Greenhouse 使用 Spring 3.1 的新环境 Bean 功能,该功能可以识别仅为特定配置文件创建的 Bean。设置该属性表示应用程序应使用“embedded”配置文件运行。

结论

Spring Social 1.0 M1 是将社交网络功能引入 Spring 的激动人心旅程的第一步。我鼓励您下载 Spring Social查看代码,并通过问题跟踪Spring Social 论坛Greenhouse 邮件列表提供反馈。

获取 Spring Newsletter

关注 Spring Newsletter

订阅

抢先一步

VMware 提供培训和认证,助您快速提升技能。

了解更多

获取支持

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

了解更多

即将举行的活动

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

查看全部