Статьи

Создание собственного SpringBoot Starter для Twitter4j

SpringBoot предоставляет множество стартовых модулей для быстрого запуска и запуска. Механизм автоматической настройки SpringBoot заботится о настройке SpringBeans от нашего имени на основе различных критериев.

В дополнение к стартовым устройствам Springboot, поставляемым Core-Team, мы также можем создавать собственные стартовые модули.

В этом посте мы рассмотрим, как создать собственный стартер SpringBoot. Чтобы продемонстрировать это, мы собираемся создать twitter4j-spring-boot-starter, который будет автоматически настраивать компоненты Twitter4J.

Для этого мы собираемся создать:

  1. Модуль twitter4j-spring-boot-autoconfigure, который содержит определения bean-компонента автоконфигурации Twitter4J
  2. Модуль twitter4j-spring-boot-starter, который извлекает зависимости twitter4j-spring-boot-autoconfigure и twitter4j-core
  3. Пример приложения, которое использует twitter4j-spring-boot-starter

Создать родительский модуль spring-boot-starter-twitter4j

Сначала мы собираемся создать родительский модуль типа pom для определения версий зависимостей и подмодулей.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                        http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.sivalabs</groupId>
    <artifactId>spring-boot-starter-twitter4j</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>spring-boot-starter-twitter4j</name>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <twitter4j.version>4.0.3</twitter4j.version>
        <spring-boot.version>1.3.2.RELEASE</spring-boot.version>
    </properties>
 
    <modules>
        <module>twitter4j-spring-boot-autoconfigure</module>
        <module>twitter4j-spring-boot-starter</module>
        <module>twitter4j-spring-boot-sample</module>
    </modules>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
 
            <dependency>
                <groupId>org.twitter4j</groupId>
                <artifactId>twitter4j-core</artifactId>
                <version>${twitter4j.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
</project>

В этом файле pom.xml мы определяем версии SpringBoot и Twitter4j в разделе, так что нам не нужно указывать версии повсюду.

Создать модуль twitter4j-spring-boot-autoconfigure

Создайте дочерний модуль с именем twitter4j-spring-boot-autoconfigure в нашем родительском модуле maven spring-boot-starter-twitter4j .

Добавьте зависимости maven, такие как spring-boot, spring-boot-autoconfigure , twitter4j-core и junit, следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
               http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sivalabs</groupId>
    <artifactId>twitter4j-spring-boot-autoconfigure</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
 
    <parent>
        <groupId>com.sivalabs</groupId>
        <artifactId>spring-boot-starter-twitter4j</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.twitter4j</groupId>
            <artifactId>twitter4j-core</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

Обратите внимание, что мы указали twitter4j-core как необязательную зависимость, потому что twitter4j-core должен быть добавлен в проект, только когда twitter4j-spring-boot-starter добавлен в проект.

Создайте свойства Twitter4j для хранения параметров конфигурации Twitter4J

Создайте Twitter4jProperties.java для хранения параметров конфигурации Twitter4J OAuth.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.sivalabs.spring.boot.autoconfigure;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
 
@ConfigurationProperties(prefix= Twitter4jProperties.TWITTER4J_PREFIX)
public class Twitter4jProperties {
 
    public static final String TWITTER4J_PREFIX = "twitter4j";
 
    private Boolean debug = false;
 
    @NestedConfigurationProperty
    private OAuth oauth = new OAuth();
 
    public Boolean getDebug() {
        return debug;
    }
 
    public void setDebug(Boolean debug) {
        this.debug = debug;
    }
 
    public OAuth getOauth() {
        return oauth;
    }
 
    public void setOauth(OAuth oauth) {
        this.oauth = oauth;
    }
 
    public static class OAuth {
 
        private String consumerKey;
        private String consumerSecret;
        private String accessToken;
        private String accessTokenSecret;
 
        public String getConsumerKey() {
            return consumerKey;
        }
        public void setConsumerKey(String consumerKey) {
            this.consumerKey = consumerKey;
        }
        public String getConsumerSecret() {
            return consumerSecret;
        }
        public void setConsumerSecret(String consumerSecret) {
            this.consumerSecret = consumerSecret;
        }
        public String getAccessToken() {
            return accessToken;
        }
        public void setAccessToken(String accessToken) {
            this.accessToken = accessToken;
        }
        public String getAccessTokenSecret() {
            return accessTokenSecret;
        }
        public void setAccessTokenSecret(String accessTokenSecret) {
            this.accessTokenSecret = accessTokenSecret;
        }
    }
}

С помощью этого объекта конфигурации мы можем настроить свойства twitter4j в application.properties следующим образом:

1
2
3
4
5
twitter4j.debug=true
twitter4j.oauth.consumer-key=your-consumer-key-here
twitter4j.oauth.consumer-secret=your-consumer-secret-here
twitter4j.oauth.access-token=your-access-token-here
twitter4j.oauth.access-token-secret=your-access-token-secret-here

Создать Twitter4jAutoConfiguration для автоматической настройки Twitter4J

Здесь идет ключевая часть нашего стартера.

Класс конфигурации Twitter4jAutoConfiguration содержит определения компонентов, которые будут автоматически настроены на основе некоторых критериев.

Что это за критерии?

  • Если twitter4j.TwitterFactory .class находится на пути к классам
  • Если bean-компонент TwitterFactory явно не определен

Итак, конфигурация Twitter4jAutoConfiguration выглядит следующим образом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.sivalabs.spring.boot.autoconfigure;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;
 
@Configuration
@ConditionalOnClass({ TwitterFactory.class, Twitter.class })
@EnableConfigurationProperties(Twitter4jProperties.class)
public class Twitter4jAutoConfiguration {
 
    private static Log log = LogFactory.getLog(Twitter4jAutoConfiguration.class);
 
    @Autowired
    private Twitter4jProperties properties;
 
    @Bean
    @ConditionalOnMissingBean
    public TwitterFactory twitterFactory(){
 
        if (this.properties.getOauth().getConsumerKey() == null
            || this.properties.getOauth().getConsumerSecret() == null
            || this.properties.getOauth().getAccessToken() == null
            || this.properties.getOauth().getAccessTokenSecret() == null)
        {
            String msg = "Twitter4j properties not configured properly." +
                         " Please check twitter4j.* properties settings in configuration file.";
            log.error(msg);
            throw new RuntimeException(msg);
        }
 
        ConfigurationBuilder cb = new ConfigurationBuilder();
        cb.setDebugEnabled(properties.getDebug())
          .setOAuthConsumerKey(properties.getOauth().getConsumerKey())
          .setOAuthConsumerSecret(properties.getOauth().getConsumerSecret())
          .setOAuthAccessToken(properties.getOauth().getAccessToken())
          .setOAuthAccessTokenSecret(properties.getOauth().getAccessTokenSecret());
        TwitterFactory tf = new TwitterFactory(cb.build());
        return tf;
    }
 
    @Bean
    @ConditionalOnMissingBean
    public Twitter twitter(TwitterFactory twitterFactory){
        return twitterFactory.getInstance();
    }
 
}

Мы использовали @ConditionalOnClass ({TwitterFactory.class, Twitter.class}), чтобы указать, что эта автоматическая конфигурация должна выполняться только при наличии классов TwitterFactory.class, Twitter.class .

Мы также использовали @ConditionalOnMissingBean в методах определения bean-компонента, чтобы указать, учитывают ли это определение bean-компонента, только если bean-компоненты TwitterFactory / Twitter еще не определены явно.

Также обратите внимание, что мы аннотировали @EnableConfigurationProperties (Twitter4jProperties.class), чтобы включить поддержку ConfigurationProperties и внедренного компонента Twitter4jProperties .

Теперь нам нужно настроить наш собственный Twitter4jAutoConfiguration в файле src / main / resources / META-INF / spring.factories следующим образом:

org.springframework.boot.autoconfigure.EnableAutoConfiguration =
com.sivalabs.spring.boot.autoconfigure.Twitter4jAutoConfiguration

Создать модуль twitter4j-spring-boot-starter

Создайте дочерний модуль с именем twitter4j-spring-boot-starter в нашем родительском модуле maven spring-boot-starter-twitter4j.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                        http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sivalabs</groupId>
    <artifactId>twitter4j-spring-boot-starter</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
 
    <parent>
        <groupId>com.sivalabs</groupId>
        <artifactId>spring-boot-starter-twitter4j</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sivalabs</groupId>
            <artifactId>twitter4j-spring-boot-autoconfigure</artifactId>
            <version>${project.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.twitter4j</groupId>
            <artifactId>twitter4j-core</artifactId>
        </dependency>
 
    </dependencies>
 
</project>

Обратите внимание, что в этом модуле maven мы фактически выявляем зависимость twitter4j-core .

Нам не нужно добавлять какой-либо код в этот модуль, но при желании мы можем указать, какие зависимости мы собираемся предоставить через этот стартер, в файле src / main / resources / META-INF / spring.provides следующим образом:

обеспечивает: twitter4j-core

Это все для нашего стартера.

Давайте создадим образец, используя наш новый стартер twitter4j-spring-boot-starter .

Создать пример приложения twitter4j-spring-boot-sample

Давайте создадим простое приложение SpringBoot и добавим нашу зависимость twitter4j-spring-boot-starter .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                        http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sivalabs</groupId>
    <artifactId>twitter4j-spring-boot-sample</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.2.RELEASE</version>
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
    <dependencies>
 
        <dependency>
            <groupId>com.sivalabs</groupId>
            <artifactId>twitter4j-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
</project>

Создайте класс точки входа SpringbootTwitter4jDemoApplication следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
package com.sivalabs.demo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class SpringbootTwitter4jDemoApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(SpringbootTwitter4jDemoApplication.class, args);
    }
}

Создайте TweetService следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.sivalabs.demo;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import twitter4j.ResponseList;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
 
@Service
public class TweetService {
 
    @Autowired
    private Twitter twitter;
 
    public List<String> getLatestTweets(){
        List<String> tweets = new ArrayList<>();
        try {
            ResponseList<Status> homeTimeline = twitter.getHomeTimeline();
            for (Status status : homeTimeline) {
                tweets.add(status.getText());
            }
        } catch (TwitterException e) {
            throw new RuntimeException(e);
        }
        return tweets;
    }
}

Теперь создайте тест для проверки нашей автоконфигурации Twitter4j.

Перед этим убедитесь, что в параметре конфигурации oauth twitter4j установлены фактические значения. Вы можете получить их с https://apps.twitter.com/

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.sivalabs.demo;
 
import java.util.List;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import twitter4j.TwitterException;
 
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SpringbootTwitter4jDemoApplication.class)
public class SpringbootTwitter4jDemoApplicationTest  {
 
 
    @Autowired
    private TweetService tweetService;
 
    @Test
    public void testGetTweets() throws TwitterException {
        List<String> tweets = tweetService.getLatestTweets();
        for (String tweet : tweets) {
            System.err.println(tweet);
        }
    }
 
}

Теперь вы должны видеть последние твиты на консоли.