通过Spring Social推特StackExchange –第1部分

本文将介绍一个快速的附带项目-一个自动从各种Q&A StackExchange网站上发布热门问题的机器人,例如StackOverflowServerFaultSuperUser等。我们将为StackExchange API构建一个简单的客户端,然后进行设置使用Spring Social与Twitter API的交互-这第一部分将仅关注StackExchange Client。 此实现的最初目的不是要成为整个StackExchange API的完整客户端-这不在本项目的范围之内。 客户端存在的唯一原因是,我无法对与正式API的2.x版本兼容的对象进行罚款。

1. Maven依赖

要使用StackExchange REST API,我们将需要很少的依赖项-本质上只是一个HTTP客户端-Apache HttpClient可以很好地满足此目的:

<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.2.3</version>
</dependency

还可以使用Spring RestTemplate与HTTP API进行交互,但这会在项目中引入很多其他与Spring相关的依赖项,这些依赖项不是严格必需的,因此HttpClient将使事情变得轻而易举。

2.问题客户

该客户端的目的是使用StackExchange 发布/ questions REST服务,而不是为整个StackExchange API提供通用客户端–因此,出于本文的目的,我们仅着眼于此。 使用HTTPClient的实际HTTP通信相对简单:

public String questions(int min, String questionsUri) {
   HttpGet request = null;
   try {
      request = new HttpGet(questionsUri);
      HttpResponse httpResponse = client.execute(request);
      InputStream entityContentStream = httpResponse.getEntity().getContent();
      return IOUtils.toString(entityContentStream, Charset.forName('utf-8'));
   } catch (IOException ex) {
      throw new IllegalStateException(ex);
   } finally {
      if (request != null) {
         request.releaseConnection();
      }
   }
}

这种简单的交互非常适合获取API发布的原始JSON问题–下一步将处理该JSON。 这里有一个相关的细节-也就是questionsUri方法参数 -有多个StackExchange API可以发布问题(如官方文档所建议的那样),并且此方法必须足够灵活才能使用所有问题。 例如,它可以使用最简单的API(通过将questionUri设置为https://api.stackexchange.com/2.1/questions?site=stackoverflow来返回问题),也可以使用基于https://api.stackexchange.com/的标记取而代之的是2.1 / tags / {tags} / faq?site = stackoverflow API,具体取决于客户端的需求。

对StackExchange API的请求已完全配置有查询参数,即使是对于更复杂的高级搜索查询,也没有发送正文。 为了构造questionsUri ,我们将构建一个基本的流畅的RequestBuilder类,该类将使用 HttpClient库中的URIBuilder 。 这将确保正确编码URI,并通常确保最终结果有效:

public class RequestBuilder {
   private Map<String, Object> parameters = new HashMap<>();
   public RequestBuilder add(String paramName, Object paramValue) {
       this.parameters.put(paramName, paramValue);
      return this;
   }
   public String build() {
      URIBuilder uriBuilder = new URIBuilder();
      for (Entry<String, Object> param : this.parameters.entrySet()) {
         uriBuilder.addParameter(param.getKey(), param.getValue().toString());
      }
      return uriBuilder.toString();
   }
}

现在,为StackExchange API构造一个有效的URI:

String params = new RequestBuilder().
   add('order', 'desc').add('sort', 'votes').add('min', min).add('site', site).build();
return 'https://api.stackexchange.com/2.1/questions' + params;

3.测试客户端

客户端将输出原始JSON,但是要进行测试,我们需要一个JSON处理库,特别是Jackson 2

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.1.3</version>
   <scope>test</scope>
</dependency>

我们将看到的测试将与实际的StackExchange API交互:

@Test
public void whenRequestIsPerformed_thenSuccess()
      throws ClientProtocolException, IOException {
   HttpResponse response = questionsApi.questionsAsResponse(50, Site.serverfault);
   assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
@Test
public void whenRequestIsPerformed_thenOutputIsJson()
      throws ClientProtocolException, IOException {
   HttpResponse response = questionsApi.questionsAsResponse(50, Site.serverfault);
   String contentType = httpResponse.getHeaders(HttpHeaders.CONTENT_TYPE)[0].getValue();
   assertThat(contentType, containsString('application/json'));
}
@Test
public void whenParsingOutputFromQuestionsApi_thenOutputContainsSomeQuestions()
     throws ClientProtocolException, IOException {
   String questionsAsJson = questionsApi.questions(50, Site.serverfault);
   JsonNode rootNode = new ObjectMapper().readTree(questionsAsJson);
   ArrayNode questionsArray = (ArrayNode) rootNode.get('items');
   assertThat(questionsArray.size(), greaterThan(20));
}

第一次测试已验证API提供的响应确实为200 OK,因此检索问题的GET请求实际上是成功的。 在确保基本条件之后,我们继续使用Content-Type HTTP标头指定的表示形式,该表示形式必须为JSON。 接下来,我们实际上解析JSON并验证输出中是否确实存在问题-解析逻辑本身是低级且简单的,足以满足测试目的。 请注意,这些请求计入API指定的速率限制 -出于这个原因,实时测试不包含在标准Maven版本中:

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.13</version>
   <configuration>
      <excludes>
         <exclude>**/*LiveTest.java</exclude>
      </excludes>
   </configuration>
</plugin>

4.下一步

当前的Client仅专注于StackExchange API发布的许多可用类型中的一种资源。 这是因为它的最初目的是有限的–仅需要使用户能够使用StackExchange产品组合中各个站点的问题 。 因此,可以改进客户端,使其超出此初始用例的范围,以能够使用其他类型的API 。 实现也非常原始 -使用Questions REST服务后,它只是将JSON输出作为字符串返回-而不是从该输出中输出任何类型的Questions模型。 因此,下一步可能是将JSON解组到适当的域DTO中,然后将其返回而不是原始JSON。

5.结论

本文的目的是演示如何开始与StackExchange API或实际上是基于HTTP的API建立集成。 它涵盖了如何针对实时API编写集成测试,以及如何确保端到端交互确实有效。

本文的第二部分将展示如何使用Spring Social库与Twitter API进行交互,以及如何使用我们在此处构建的StackExchange Client在新的Twitter帐户上发布问题。

我已经建立了一些Twitter帐户,现在每天在Twitter上发布各种学科的2个热门问题:

  • SpringAtSO –每天来自StackOverflow的两个最佳Spring问题
  • JavaTopSO –每天来自StackOverflow的两个最佳Java问题
  • AskUbuntuBest –每天来自AskUbuntu的两个最佳问题
  • BestBash –每天来自所有StackExchange网站的两个最佳Bash问题
  • ServerFaultBest –每天来自ServerFault的两个最佳问题

该StackExchange Client的完整实现在github上

参考: 使用Spring Social 推销StackExchange –第一部分,来自JCG合作伙伴 Eugen Paraschiv,来自baeldung博客。

翻译自: https://www.javacodegeeks.com/2013/02/tweeting-stackexchange-with-spring-social-part-1.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值