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

1. Использование Spring Social Twitter

Необходимые зависимости, необходимые для использования проекта Spring Social Twitter, просты. Во-первых, мы определяем сам spring-social-twitter:

<dependency>
   <groupId>org.springframework.social</groupId>
   <artifactId>spring-social-twitter</artifactId>
   <version>1.1.0.RELEASE</version>
</dependency>

Затем нам нужно переопределить некоторые из его зависимостей более современными версиями:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>4.1.0.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>4.1.0.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.codehaus.jackson</groupId>
   <artifactId>jackson-mapper-asl</artifactId>
   <version>1.9.13</version>
</dependency>

Spring-core и spring-web определены как зависимости spring-social-twitter, но с более старыми версиями — 3.0.7.RELEASE и 3.1.0.RELEASE соответственно. Переопределение их в нашем собственном pom гарантирует, что проект использует актуальные версии, которые мы определили, вместо этих более старых унаследованных версий.

2. Создание приложения Twitter

Этот вариант использования — размещение твитов в личной учетной записи, а не от имени других пользователей в их учетных записях — является простым. Тот факт, что это просто, позволяет нам обойтись без большей части OAuth-оркестровки, необходимой, если приложению потребуется твитить для нескольких пользователей в каждой из их учетных записей Twitter.

Итак, для нашего варианта использования мы создадим TwitterTemplate напрямую, так как мы можем вручную настроить все, что нам нужно для этого.

Первое, что нам нужно, это приложение разработчика — его можно создать здесь после входа в систему. После создания приложения у нас будет ключ потребителя и секрет потребителя — их можно получить на странице приложения – на вкладке «Сведения» в настройках OAuth.

Кроме того, чтобы приложение могло публиковать твиты в учетной записи, необходимо установить доступ для чтения и записи, чтобы заменить привилегии только для чтения по умолчанию.

3. Инициализация TwitterTemplate

Далее, TwitterTemplate требует предоставления токена доступа и секрета токена доступа. Их также можно сгенерировать на странице приложения — на вкладке «Сведения» — создать мой токен доступа. Затем и токен доступа, и секрет можно получить на вкладке инструмента OAuth.

Новые всегда можно создать повторно на вкладке «Сведения» с помощью действия «Восстановить мой токен доступа».

На данный момент у нас есть все, что нам нужно — Consumer Key и Consumer Secret, а также Access Token и Access Token Secret — что означает, что мы можем двигаться вперед и создать наш TwitterTemplate для этого приложения: ~~ ~

new TwitterTemplate(consumerKey, consumerSecret, accessToken, accessTokenSecret);

4. Один шаблон для каждой учетной записи

Теперь, когда мы увидели, как создать один TwitterTemplate для одной учетной записи, мы можем снова оглянуться назад на наш пример использования — нам нужно твитнуть на несколько учетных записей — это означает, что нам нужно несколько экземпляров TwitterTemplate.

Их можно легко создать по запросу с помощью простого механизма:

@Component
public class TwitterTemplateCreator {
   @Autowired
   private Environment env;

   public Twitter getTwitterTemplate(String accountName) {
      String consumerKey = env.getProperty(accountName + ".consumerKey");
      String consumerSecret = env.getProperty(accountName + ".consumerSecret");
      String accessToken = env.getProperty(accountName + ".accessToken");
      String accessTokenSecret = env.getProperty(accountName + ".accessTokenSecret");
      Preconditions.checkNotNull(consumerKey);
      Preconditions.checkNotNull(consumerSecret);
      Preconditions.checkNotNull(accessToken);
      Preconditions.checkNotNull(accessTokenSecret);

      TwitterTemplate twitterTemplate = 
         new TwitterTemplate(consumerKey, consumerSecret, accessToken, accessTokenSecret);
      return twitterTemplate;
   }
}

Четыре артефакта безопасности, конечно же, вынесены в файл свойств по учетной записи; например, для учетной записи SpringAtSO:

SpringAtSO.consumerKey=nqYezCjxkHabaX6cdte12g
SpringAtSO.consumerSecret=7REmgFW4SnVWpD4EV5Zy9wB2ZEMM9WKxTaZwrgX3i4A
SpringAtSO.accessToken=1197830142-t44T7vwgmOnue8EoAxI1cDyDAEBAvple80s1SQ3
SpringAtSO.accessTokenSecret=ZIpghEJgFGNGQZzDFBT5TgsyeqDKY2zQmYsounPafE

Это обеспечивает хорошее сочетание гибкости и безопасности — учетные данные безопасности не являются частью кодовой базы (с открытым исходным кодом), а живут независимо от файловой системы и выбираются созданный Spring и доступный в Spring Enviroment через простую конфигурацию:

@Configuration
@PropertySource({ "file:///opt/stack/twitter.properties" })
public class TwitterConfig {
    // 
}

Свойства в Spring — это тема, которая уже обсуждалась ранее, поэтому мы не будем здесь вдаваться в подробности.

Наконец, тест проверит, что учетная запись имеет необходимую информацию о безопасности, доступную в среде Spring; если свойства отсутствуют, логика getTwitterTemplate должна провалить тест с NullPointerException:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TwitterConfig.class })
public class TwitterTemplateCreatorIntegrationTest {
   @Autowired
   private TwitterTemplateCreator twitterTemplateCreator;
   //
   @Test
   public void givenValidAccountSpringAtSO_whenRetrievingTwitterClient_thenNoException() {
      twitterTemplateCreator.getTwitterTemplate(SimpleTwitterAccount.SpringAtSO.name());
   }
}

5. Твиттер

Создав TwitterTemplate, давайте обратимся к фактическому действию твитинга. Для этого мы будем использовать очень простой сервис, принимая TwitterTemplate и используя его базовый API для создания твита:

@Service
public class TwitterService {
   private Logger logger = LoggerFactory.getLogger(getClass());

   public void tweet(Twitter twitter, String tweetText) {
      try {
         twitter.timelineOperations().updateStatus(tweetText);
      } catch (RuntimeException ex) {
         logger.error("Unable to tweet" + tweetText, ex);
      }
   }
}

6. Тестирование TwitterTemplate

«И, наконец, мы можем написать интеграционный тест, чтобы выполнить весь процесс предоставления TwitterTemplate для учетной записи и публикации твитов в этой учетной записи:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TwitterConfig.class })
public class TweetServiceLiveTest {
   @Autowired
   private TwitterService twitterService;
   @Autowired
   private TwitterTemplateCreator twitterCreator;

   @Test
   public void whenTweeting_thenNoExceptions() {
      Twitter twitterTemplate = twitterCreator.getTwitterTemplate("SpringAtSO");
      twitterService.tweet(twitterTemplate, "First Tweet");
   }
}

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

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

Следующим логическим шагом в процессе отправки вопросов из учетных записей Stack Exchange в Твиттере является создание компонента, взаимодействующего как с API Twitter, так и с API StackExchange, которые мы представили до сих пор. статья из этой серии.