【Spring Integration】入門(mén)示例2例:讀取文件并移動(dòng)到另一文件夾,通過(guò)Spring Integration發(fā)送郵件

【官網(wǎng)】

【本文示例】

  • 通過(guò)spring-integration,將source文件夾中的文件自動(dòng)復(fù)制到destination文件夾中。
  • 通過(guò)spring-integration,發(fā)送email。

1. 示例-1:將source文件夾中的文件自動(dòng)復(fù)制到destination文件夾中

【示例參考】

1.1 依賴

需要引入spring boot parent,我用的是2.7.0版本。這個(gè)版本的spring boot,相應(yīng)引入的spring-integration版本為5.5.12。
下述的spring-integration-file主要是示例中需要操作file。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-file</artifactId>
        </dependency>
    </dependencies>
1.2 核心代碼,創(chuàng)建兩個(gè)bean
  • 首先是注解@EnableIngetration,java文檔:地址,這個(gè)注解是spring-integration 4.0版本后引入的,主要是激活了spring integration相關(guān)的配置,有了這個(gè)注解,可以不需要老版本的xml配置,除此之外還會(huì)自動(dòng)加入相關(guān)的BeanFactoryPostProcessors等。

  • 第一個(gè)bean為@InboundChannelAdapter,即spring-integration中的Adapter(分Inbound Adapter和Outbound Adapter,下述定義的FileReadingMessageSource為Inbound Adapter),@InboundChannelAdapter注解會(huì)將這個(gè)bean標(biāo)記成Adapter,配置一個(gè)從別的系統(tǒng)接收的message(我們下述的例子為source文件夾中拿文件)。

    • Inbound Adapter中可以配置value,即channel的名字,這個(gè)在我們接收消息后的下一步(即訂閱這個(gè)inbound message)的時(shí)候要綁定上。
    • 另一個(gè)參數(shù)為poller,英文的意思是輪詢,這里配置的是每1000毫秒輪詢一次。
    • 方法中的CompositeFileListFilter是用來(lái)過(guò)濾的,不配置的話說(shuō)明讀取的是整個(gè)source文件夾中的所有文件,配置后只會(huì)讀取txt后綴的文件。
  • @ServiceActivator(java文檔:地址),它需要參數(shù)inputChannel,即接收特定的inbound channel中的消息,在消息到達(dá)到inbound channel后,在這個(gè)方法中處理。在下述的例子中,fileReadingMessageSource()方法負(fù)責(zé)從source文件夾中讀取文件,當(dāng)文件讀取到channel后,fileWritingMessageHandler()會(huì)接管處理,并將文件寫(xiě)到destination文件夾中。

    • setAutoCreateDirectory表示如果沒(méi)有destination文件夾,會(huì)自動(dòng)創(chuàng)建一個(gè)。
@Configuration
@EnableIntegration
public class SpringIntegrationConfig {

    String folder = "/Users/xx/IdeaProjects/spring-integration-test/src/main";

    @Bean
    @InboundChannelAdapter(value = "fileInputChannel", poller = @Poller(fixedDelay = "1000"))
    public MessageSource<File> fileReadingMessageSource() {
        CompositeFileListFilter<File> filter = new CompositeFileListFilter<>();
        filter.addFilter(new SimplePatternFileListFilter("*.txt"));

        FileReadingMessageSource readerSource = new FileReadingMessageSource();
        readerSource.setDirectory(new File(folder + "/resources/source"));
        readerSource.setFilter(filter);
        return readerSource;
    }

    @Bean
    @ServiceActivator(inputChannel = "fileInputChannel")
    public MessageHandler fileWritingMessageHandler() {
        FileWritingMessageHandler writerHandler =
                new FileWritingMessageHandler(new File(folder + "/resources/destination"));
        writerHandler.setAutoCreateDirectory(true);
        writerHandler.setExpectReply(false);
        return writerHandler;
    }
1.3 測(cè)試

首先在resources目錄下新建source文件夾,并放一些測(cè)試文件:
image.png

啟動(dòng)SpringIntegrationApplication,從日志可以看到創(chuàng)建了channel=fileInputChannel,并且該channel有一個(gè)訂閱者:

2022-11-27 21:59:36.722 INFO 37452 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {file:outbound-channel-adapter:springIntegrationConfig.fileWritingMessageHandler.serviceActivator} as a subscriber to the 'fileInputChannel' channel
2022-11-27 21:59:36.722 INFO 37452 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application.fileInputChannel' has 1 subscriber(s).

啟動(dòng)后可以看到文件test.txt被自動(dòng)復(fù)制到了destination文件夾中:
image.png

2. 示例-2:通過(guò)spring-integration,發(fā)送email

【參考】

【官方文檔】

2.1 依賴

和#1一樣,需要引入spring boot parent,我用的是2.7.0版本。上述的spring-boot-starter-integration也需要引入。除此之外,還需要引入mail相關(guān)的依賴:

  • spring-integration-mail和spring-integration一樣,會(huì)自動(dòng)關(guān)聯(lián)5.5.12版本。
  • javax.mail是用來(lái)發(fā)郵件的。
  • dumbster相當(dāng)于測(cè)試的時(shí)候Mock了一個(gè)郵件服務(wù)器。
<dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>com.github.kirviq</groupId>
            <artifactId>dumbster</artifactId>
            <version>1.7.1</version>
            <scope>test</scope>
        </dependency>
</dependency>
2.2 Mail相關(guān)配置:

新建配置文件:smtp.properties

smtp.host=localhost
smtp.port=12345
2.3 核心代碼:創(chuàng)建三個(gè)bean
  • 第一個(gè)bean,JavaMailSenderImpl,創(chuàng)建郵件發(fā)送的bean,跟spring-integration本身無(wú)關(guān),就是email發(fā)送的bean。用創(chuàng)建出來(lái)的mailSender bean直接發(fā)郵件也是可以的,調(diào)用send()即可。
  • 第二個(gè)bean,創(chuàng)建smtpChannel用來(lái)接收email messages用來(lái)發(fā)送郵件,這個(gè)bean也可以不創(chuàng)建,如果沒(méi)有創(chuàng)建Spring也會(huì)幫我們創(chuàng)建,關(guān)于DirectChannel,實(shí)質(zhì)上是spring-messaging.jar中的MessageChannel 接口,關(guān)于message-channel,可以查看官方文檔:https://docs.spring.io/spring-integration/reference/html/channel.html。
  • 第三個(gè)bean,我們使用mailsSenderMessagingHandler bean來(lái)發(fā)送郵件,當(dāng)它收到的message的playload是MailMessage(來(lái)自smtpChannel),他就會(huì)發(fā)送給smtp server。
@Configuration
@PropertySource("classpath:/smtp.properties")
public class MailConfig {

    @Value("${smtp.host}")
    private String smptHost;

    @Value("${smtp.port}")
    private Integer smtpPort;

    @Bean
    public JavaMailSenderImpl mailSender() {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(smptHost);
        mailSender.setPort(smtpPort);
        return mailSender;
    }

    @Bean
    public MessageChannel smtpChannel() {
        return new DirectChannel();
    }

    @ServiceActivator(inputChannel = "smtpChannel", outputChannel = "nullChannel")
    public MessageHandler mailsSenderMessagingHandler (Message<MailMessage> message) {
        MailSendingMessageHandler mailSendingMessageHandler = new MailSendingMessageHandler(mailSender());
        mailSendingMessageHandler.handleMessage(message);
        return mailSendingMessageHandler;
    }
}

【測(cè)試】

  • 可以看到我們使用了smtpChannel的send方法,本質(zhì)上還是調(diào)用了MessageChannel接口,這里send的消息會(huì)被integration中的mailsSenderMessagingHandler接收,然后它進(jìn)行處理,這里是通過(guò)MailSendingMessageHandler進(jìn)行發(fā)送郵件。
  • 另外SimpleSmtpServer.start(12345)則是使用了dumbster包的mock郵件服務(wù)器。
@Slf4j
@SpringBootTest
public class MailTest {

    @Autowired
    MessageChannel smtpChannel;

    @Test
    public void mailsend() throws IOException {
        SimpleSmtpServer mailServer = SimpleSmtpServer.start(12345);
        smtpChannel.send(new GenericMessage<>(buildMailMessage("Test 1", "content 1")));
        mailServer.stop();

        log.info("email send successfully..............");
        List<SmtpMessage> messagesSent = mailServer.getReceivedEmails();
        Assertions.assertEquals(1, messagesSent.size());

        log.info("received body: {}", messagesSent.get(0).getBody());
    }

    private MailMessage buildMailMessage(String subject, String content){
        MailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setTo("test-to@com.test");
        mailMessage.setFrom("noreply@com.test");
        mailMessage.setCc("test-cc@com.test");
        mailMessage.setText(content);
        mailMessage.setSubject(subject);
        return mailMessage;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容