Учебные материалы

Обработка данных

В этом уроке освещается процесс создания простого приложения c использованием Spring Integration, которое получает данные из Twitter, манипулирет ими, а потом пишет в файл.

Что вы создадите

Вы создадите поток c использованием Spring Integration.

Что вам потребуется

  • Примерно 15 минут свободного времени
  • Любимый текстовый редактор или IDE
  • JDK 6 и выше
  • Gradle 1.11+ или Maven 3.0+
  • Вы также можете импортировать код этого урока, а также просматривать web-страницы прямо из Spring Tool Suite (STS), собственно как и работать дальше из него.

Как проходить этот урок

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

Чтобы начать с нуля, перейдите в Настройка проекта.

Чтобы пропустить базовые шаги, выполните следующее:

Когда вы закончите, можете сравнить получившийся результат с образцом в gs-integration/complete.

Настройка проекта

Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle и Maven. Если вы не знакомы ни с одним из них, ознакомьтесь с соответсвующими уроками Сборка Java-проекта с использованием Gradle или Сборка Java-проекта с использованием Maven.

Создание структуры каталогов

В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру, командой mkdir -p src/main/java/hello для *nix систем:

└── src
    └── main
        └── java
            └── hello

Создание файла сборки Gradle

Ниже представлен начальный файл сборки Gradle. Файл pom.xml находится здесь. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.

Если вы посмотрите на pom.xml, вы найдете, что указана версия для maven-compiler-plugin. В общем, это не рекомендуется делать. В данном случае он предназначен для решения проблем с нашей CI системы, которая по умолчанию имеет старую(до Java 5) версию этого плагина.

build.gradle

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-release" }
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.8.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-integration'
    version =  '0.1.0'
}

repositories {
    mavenLocal()
    mavenCentral()
    maven { url "http://repo.spring.io/libs-release" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-integration")
    compile("org.springframework.integration:spring-integration-twitter:4.0.3.RELEASE")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}

Spring Boot gradle plugin предоставляет множество удобных возможностей:

  • Он собирает все jar'ы в classpath и собирает единое, исполняемое "über-jar", что делает более удобным выполнение и доставку вашего сервиса
  • Он ищет public static void main() метод, как признак исполняемого класса
  • Он предоставляет встроенное разрешение зависимостей, с определенными номерами версий для соответсвующих Spring Boot зависимостей. Вы можете переопределить на любые версии, какие захотите, но он будет по умолчанию для Boot выбранным набором версий

Описание плана интеграции

В этом учебном приложении вы опишите Spring Integration план, который читает твиты из Twitter, трансформирует их в легкочитаемые String, а затем дабавляет их в конец файла.

Чтобы описать интеграционный план, вы просто создаете Spring XML конфигурацию из нескольких элементов пространства имен Spring Integration XML, в частности: core, twitter и file.

Ниже приведен XML файл конфигурации, описывающий план интеграции.

src/main/resources/hello/integration.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:twitter="http://www.springframework.org/schema/integration/twitter"
    xmlns:file="http://www.springframework.org/schema/integration/file"
    xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file-2.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter-2.2.xsd">

    <twitter:search-inbound-channel-adapter id="tweets"
            query="#HelloWorld"
            twitter-template="twitterTemplate">
        <int:poller fixed-rate="5000"/>
    </twitter:search-inbound-channel-adapter>

    <int:transformer
            input-channel="tweets"
            expression="payload.fromUser + '  :  ' + payload.text + @newline"
            output-channel="files"/>

    <file:outbound-channel-adapter id="files"
            mode="APPEND"
            charset="UTF-8"
            directory="/tmp/si"
            filename-generator-expression="'HelloWorld'"/>

</beans>

Как видите, задействованы всего три элемента интеграции:

  • <twitter:search-inbound-channel-adapter>. Входящий адаптер, который ищет твиты с "#HelloWorld" в тексте. Он инициализирует TwitterTemplate из Spring Social для выполнения соответствующего поиска. В данной конфигурации он настроен на опрос каждые 5 секунд. Любые соответсвующие твиты будут помещены в канал с названием "tweets" (в соответствии с ID адаптера)
  • <int:transformer>. Трансформирование твитов в канале "tweets" состоит в извлечении автора(payload.fromUser), текста(payload.text) и объединение их в читаемую String. Затем она записывается в исходящий канал "files"
  • <file:outbound-channel-adapter>. Исходящий адаптер, который записывает содержимое из канала(здесь он назван "files") в файл. В данной конфигурации он настроен на добавление чего-либо из канала "files" в файл /tmp/si/HelloWorld

Пример потока иллюстрирован ниже:

Интеграционный план ссылается на два бины, которые не описаны в integration.xml: бин "twitterTemplate", который введен во входящий адаптер поиска и бин "newline", бин в трансформере. Эти бины будут описаны отдельно от JavaConfig как часть главного класса приложения.

Создание приложения исполняемым

Несмотря на то, что это обобщенная конфигурация Spring Integration плана для больших приложений, а возможно даже и для web-приложения, нет никаких причин не описывать её для простых самостоятельных приложений. Поэтому далее вы создаете главный класс, который запускает интеграционный план, а также инициализирует для его поддержки несколько бинов. Вы также можете собрать приложение в отдельный исполняемый JAR файл.

src/main/java/hello/Application.java

package hello;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.env.Environment;
import org.springframework.social.oauth2.OAuth2Operations;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;

@Configuration
@ImportResource("/hello/integration.xml")
public class Application {

    public static void main(String[] args) {
        new AnnotationConfigApplicationContext(Application.class);
    }

    @Bean
    public String newline() {
        return System.getProperty("line.separator");
    }

    @Bean
    public Twitter twitterTemplate(OAuth2Operations oauth2) {
        return new TwitterTemplate(oauth2.authenticateClient().getAccessToken());
    }

    @Bean
    public OAuth2Operations oauth2Template(Environment env) {
        return new OAuth2Template(env.getProperty("clientId"), env.getProperty("clientSecret"), "", "https://api.twitter.com/oauth2/token");
    }

}

Как видите, этот класс предоставляет метод main(), который загружает контекст приложения Spring. Он также содержит аннотацию @Configuration, которая означает, что класс содержит определения бинов.

В частности, создаются три бина:

  • Метод newLine() создает простой String бин, который содержит системный символ(ы) переноса строки. Он используется в плане интеграции в конце новой строки трансформированного твита.
  • Метод twitterTemplate() объявляет TwitterTemplate бин, который инициализируется в <twitter:search-inbound-channel-adapter>
  • Метод oauth2Template() объявляет Spring Social OAuth2Template бин, используемый для получения клиентского ключа доступа, когда создается предыдущий бин.

Метод oauth2Template() содержит аргумент типа Environment для получения "clientId" и "clientSecret" свойств. Значения этих свойств вы получали, когда регистрировали приложение в Twitter. Получение их из Environment означает, что вы не "зашили" их в этот класс конфигурации. Однако они вам понадобятся, когда вы будете запускать приложение.

И наконец, обратите внимание, что Application настроен с @ImportResource для импорта интеграционного плана, описаном в /hello/integration.xml.

Сборка исполняемого JAR

Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.

./gradlew build

Затем вы можете запустить JAR-файл:

java -jar build/libs/gs-integration-0.1.0.jar

Если вы используете Maven, вы можете запустить приложение, используя mvn spring-boot:run, либо вы можете собрать приложение с mvn clean package и запустить JAR примерно так:

java -jar target/gs-integration-0.1.0.jar
Процедура, описанная выше, создает исполняемый JAR. Вы также можете вместо него собрать классический WAR-файл.

Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:

./gradlew clean build && java -jar build/libs/gs-integration-0.1.0.jar
Если вы используете Maven, то можете запустить ваш сервис таким образом: mvn clean package && java -jar target/gs-integration-0.1.0.jar.

Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:

./gradlew bootRun
С mvn - mvn spring-boot:run.

Запуск приложения

Теперь вы можете запустить ваше приложение из jar:

java -DclientId={YOUR CLIENT ID} -DclientSecret={YOUR CLIENT SECRET} -jar build/libs/{project_id}-0.1.0.jar

... app starts up ...

Убедитесь, что вы указали ваши ID приложения и секретное слово в команде, как указано выше.

Как только приложение запустится, оно соединится с Twitter и начнет собирать твиты, которые соответствуют критерию поиска по "#HelloWorld". Приложение обрабатывает найденные твиты через план интеграции, добавляя автора твита и текст в файл /tmp/si/HelloWorld.

После того, как приложение проработает некоторое время, вы можете просмотреть файл /tmp/si/HelloWorld и увидеть информацию о нескольких твитах. На операционных системах UNIX можно воспользоваться командой tail, чтобы увидеть результаты, которые будут найдены.

tail -f /tmp/si/HelloWorld

Вы должны увидеть примерно следующее:

BrittLieTjauw  :  Now that I'm all caught up on the bachelorette I can leave my room #helloworld
mishra_ravish  :  Finally, integrated #eclim. #Android #HelloWorld
NordstrmPetite  :  Pink and fluffy #chihuahua #hahalol #boo #helloworld http://t.co/lelHhFN3gq
GRhoderick  :  Ok Saint Louis, show me what you got. #HelloWorld

Итог

Поздравляем! Вы только что разработали простое приложение, которое использует Spring Integration для сбора твитов из Twitter, обрабатывает, а потом записывает их в файл.

С оригинальным текстом урока вы можете ознакомиться на spring.io.

comments powered by Disqus