Рубрики
Без рубрики

StackExchange REST Клиент с весной и RestTemplate

StackExchange REST Клиент с весной и RestTemplate

Автор оригинала: Eugen Paraschiv.

StackExchange REST Клиент с весной и RestTemplate

Эта статья будет охватывать быстрый побочный проект – бот, чтобы автоматически чирикать Топ Вопросы от различных сайтов StackExchange , такие как СтекOverflow , СерверФо , Суперпользователь и так далее. Мы построим простого клиента для StackExchange API а затем мы установим взаимодействие с API Twitter с помощью Весенние социальные – эта первая часть будет сосредоточена только на StackExchange клиента.

Первоначальная цель этой реализации заключается в не быть полноценным клиентом для всего API StackExchange – это было бы вне сферы действия этого проекта. Единственная причина, по которой Клиент существует, заключается в том, что я не мог оштрафовать того, кто работал бы против версии 2.x официального API.

1. Зависимость от Maven

Чтобы потреблять API StackExchange REST, нам понадобится очень мало зависимостей – по сути просто клиент HTTP – Apache HttpClient будет делать только штрафом для этой цели:


   org.apache.httpcomponents
   httpclient
   4.3.3

Весенний RestTemplate также можно было бы использовать для взаимодействия с HTTP API, но это ввело бы довольно много других зависимостей, связанных с весной в проект, зависимостей, которые не являются строго необходимыми, так что HttpClient будет держать вещи легкими и простыми.

2. Вопросы клиента

Целью этого Клиента является потребление /вопросы Обслуживание REST то StackExchange публикует , чтобы не предоставлять клиента общей цели для всего API StackExchange – так что для целей этой статьи мы будем только смотреть на это.
Фактическое сообщение HTTP с использованием HTTPClient
относительно проста:

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();
      }
   }
}

Это простое взаимодействие вполне достаточно для получения вопросов сырья JSON, что API публикует – следующим шагом будет обработка, что JSON. Существует одна соответствующая деталь здесь – и это вопросыУри метод аргумент – Существует несколько API StackExchange, которые могут публиковать вопросы (как следует из официальной документации ), и этот метод должен быть достаточно гибким, чтобы потреблять все из них. Он может потреблять, например, самый простой API, который возвращает вопросы, устанавливая вопросУри установлен на https://api.stackexchange.com/2.1/questions?site=stackoverflow или он может потреблять тег на основе https://api.stackexchange.com/2.1/tags/«теги»/faq?site-stackoverflow API вместо этого, в зависимости от того, что нужно клиенту.

Запрос на API StackExchange полностью настроен с параметрами запроса, даже для более сложных расширенных поисковых запросов – нет тела, отправляемого. Построить вопросыУри , мы построим основные свободно RequestBuilder класс, который использовать URIBuilder из библиотеки HttpClient. Это позволит правильно кодировать URI и в целом убедиться, что конечный результат действителен:

public class RequestBuilder {
   private Map 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 param : this.parameters.entrySet()) {
         uriBuilder.addParameter(param.getKey(), param.getValue().toString());
      }

      return uriBuilder.toString();
   }
}

Так что теперь, чтобы построить действительный URI для StackExchange API:

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, в частности, Джексон 2 :


   com.fasterxml.jackson.core
   jackson-databind
   2.3.3
   test

Тесты, которые мы будем смотреть на будет взаимодействовать с фактическим 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 для получения вопросов был на самом деле успешным. После того, как основное условие будет обеспечено, мы перешли к представительству , как указано Контент-тип HTTP заголовок – что должно быть JSON. Далее, мы фактически разобрать JSON и проверить, что Есть на самом деле Вопросы в том, что выход – что анализ логики сам по себе низкий уровень и простой, что достаточно для целей теста.

Обратите внимание, что эти запросы учитываются в вашем предельные ставки указанный API – по этой причине тесты Live исключаются из стандартной сборки Maven:


   org.apache.maven.plugins
   maven-surefire-plugin
   2.17
   
      
         **/*LiveTest.java
      
   

4. Следующий шаг

Текущий Клиент ориентирован только на одного типа ресурсов из многих доступных типов, опубликованных API StackExchange. Это потому, что его первоначальная цель ограничена – это только необходимо, чтобы позволить пользователю потреблять Вопросы с различных сайтов в портфеле StackExchange. Следовательно, Клиент может быть улучшен за рамки этого первоначального usecase, чтобы иметь возможность потреблять другие типы API . Реализация также в значительной степени сырой – После потребления Вопросы REST службы, он просто возвращает JSON выход в качестве строки – не какой-либо модели вопросов из этого вывода. Таким образом, потенциальный следующий шаг будет unmarshall этого JSON в надлежащем домене DTO и вернуть, что обратно, а не сырья JSON.

5. Заключение

Цель этой статьи состояла в том, чтобы показать, как начать построение интеграции с API StackExchange, или действительно НА основе HTTP API там. В нем о том, как писать интеграционные тесты против живого API и убедиться, что от конца до конца взаимодействия на самом деле работает.

Вторая часть этой статьи покажет, как взаимодействовать с API Twitter с помощью весенней социальной библиотеки, и как использовать StackExchange Клиент мы построили здесь, чтобы чирикать вопросы на новый счет Twitter.

Я уже создал несколько щебетать счета, которые в настоящее время чирикал 2 Лучшие вопросы в день, для различных дисциплин:

  • СпрингТип – Два лучших весенних вопроса от StackOverflow каждый день
  • JavaTopSO – Два лучших Java-вопроса от StackOverflow каждый день
  • AskUbuntuBest – Два из лучших вопросов от AskUbuntu каждый день
  • БестБаш – Два из лучших Bash вопросы со всех сайтов StackExchange каждый день
  • СерверFaultBest – Два из лучших вопросов от ServerFault каждый день

Полная реализация этого StackExchange Клиент на github .