Статьи

Spring Integration: практическое пособие, часть 2

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

В части 1 новые потенциальные клиенты перенаправились в активатор службы, который вызвал локальный метод служебного компонента LeadService.createLead () , который затем сделал вид, что сохраняет потенциальную возможность в базе данных. Давайте вернемся к этому.

Маршрутизация международных приводит к внешней CRM

[Исходный код этого раздела доступен здесь, Смешная схема нумерации связана с тем, что этот раздел изначально был разделом 5 одного урока.]

Как только что упомянуто, шина в настоящее время отбрасывает записи о регистрации в базу данных потенциальных клиентов CRM. Скажем, однако, что у нас на самом деле есть несколько разных групп, вовлеченных в обработку заявок на регистрацию: одна команда для внутренних (США) и другая для международных лидов. Международная команда уже использует отдельную унаследованную CRM, которую в конечном итоге мы планируем поэтапно прекратить, но сейчас нам нужно ее использовать. Таким образом, проблема состоит в том, чтобы направить внутренние каналы к CRM, который использует местная команда, а международные команды к устаревшей CRM.

На рисунке 1 показано, как мы собираемся использовать маршрутизатор для решения этой проблемы.

 

 

 


Рисунок 1. Отправка внутренних лидов в локальную CRM, а международных лидов — в другую CRM.

Чтобы реализовать все это, нам нужно позаботиться о нескольких вещах, включая создание фиктивного внешнего CRM для международных лидов, обновление локального POM CRM, обновление класса Lead для поддержки маршрутизации и сериализации на основе контента в XML и добавление дополнительных компонентов. Конфигурация для applicationContext -gration.xml для построения новых частей конвейера.

Сначала мы позаботимся о фиктивной внешней CRM, так как она автономна.

Создать фиктивную внешнюю CRM для международных лидов

Мы не будем раскрывать здесь детали, но в примере кода мы добавили новый модуль Maven с именем xcrm (для «External CRM») в POM верхнего уровня. Все, что он содержит, — это некоторые файлы конфигурации и фиктивная конечная точка веб-службы, реализованная в виде простого старого сервлета, для регистрации полезной нагрузки HTTP-запроса на консоли. Это наша «CRM». Это позволит нам увидеть SOAP-сообщение, которое мы отправим в ближайшее время, что, конечно, является реальным моментом, когда мы его включили.

Теперь нам нужно сделать несколько обновлений для локальной CRM. Мы начнем с POM и пойдем оттуда.

Обновите CRM POM

Есть несколько зависимостей POM, которые мы должны добавить в crm / pom.xml , в основном это веб-сервисы XML и SOAP. Смотрите код загрузки для деталей. Я использовал профиль Maven для поддержки Java 5. Если вы точно знаете, что используете Java 5, вы можете просто добавить эти зависимости в раздел POM зависимостей вместо того, чтобы добавлять их в профиль. В качестве альтернативы, если вы точно знаете, что используете Java 6, вы можете полностью их опустить, так как они включены в Java 6 SDK.

Вам также необходимо добавить свойства spring.ws.version , jaxb.version и saaj.version .

Теперь давайте проверим класс Lead . Есть несколько разных вещей, которые нам нужно сделать.

Читатели DZone получают скидку 30% на практикеИспользуйте код dzone30  при проверке любой версии книги на www.manning.com .

Разработайте класс Lead и аннотируйте его для OXM

В листинге 1 показан наш обновленный класс Lead . Пожалуйста, смотрите код загрузки для полной версии.

Листинг 1. Аннотирование Lead.java для поддержки отображения объектов / XML

package crm.model;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement
@XmlType(propOrder = {
"firstName", "lastName",
"address1", "address2", "city", "stateOrProvince", "postalCode", "country",
"homePhone", "workPhone", "mobilePhone", "email" })
public class Lead {

... various fields (firstName, etc.) ...

public Lead() { }

@XmlElement(name = "givenName")
public String getFirstName() { return firstName; }

public void setFirstName(String firstName) { this.firstName = firstName; }

@XmlTransient
public String getMiddleInitial() { return middleInitial; }

public void setMiddleInitial(String middleInitial) {
this.middleInitial = middleInitial;
}

@XmlElement(name = "surname")
public String getLastName() { return lastName; }

public void setLastName(String lastName) { this.lastName = lastName; }

public String getFullName() { return firstName + " " + lastName; }

... various getters and setters ...

@XmlElement
public String getCountry() { return country; }

public void setCountry(String country) { this.country = country; }

public boolean isInternational() {
boolean unknown = (country == null);
boolean domestic = ("US".equals(country));
return !(unknown || domestic);
}

... even more getters and setters ...
}

Первое, что нужно обсудить, — это новый метод isInternational () . Это возвращает логическое значение, указывающее, является ли лидерство международным лидерством. Если страна пуста или «США», она не международная; в противном случае это так. (Пример кода включает в себя модульное тестирование для этого метода.) Мы добавляем этот метод, потому что мы собираемся создать маршрутизатор на основе контента всего за несколько минут. Маршрутизатор запросит метод isInternational () ведущего и примет решение о маршрутизации на основе этого результата.

Другое изменение заключается в том, что мы добавили несколько аннотаций JAXB для поддержки сопоставления объектов / XML (OXM). Это позволит нам сгенерировать ведущий документ, который мы можем отправить на внешнюю CRM в виде сообщения SOAP. Мы не делаем ничего особенно сложного здесь, но это помогает понять суть. Есть некоторая конфигурация Spring Integration, которую нам нужно сделать, чтобы активировать OXM, и мы увидим это в разделе 1.5 ниже. Однако до этого давайте создадим маршрутизатор контента.

Добавить ведущую маршрутизацию

На рисунке 1 есть маршрутизатор, который расположен между newLeadChannel с одной стороны и двумя CRM с другой. Этот маршрутизатор поддерживается POJO, показанным в листинге 2 ниже.

Листинг 2. CountryRouter.java , роутер POJO

package crm.integration.routers;

import java.util.logging.Logger;
import org.springframework.integration.annotation.Router;
import crm.model.Lead;

public class CountryRouter {
private static Logger log = Logger.getLogger("global");

@Router
public String route(Lead lead) {
String destination = (lead.isInternational() ?
"internationalChannel" : "domesticChannel");
log.info("Lead country is " +
lead.getCountry() + "; routing to " + destination);
return destination;
}
}

Это простой компонент с единственным методом route (), который мы аннотировали аннотацией @Router, чтобы Spring Integration знала, какой метод использовать для маршрутизации. Должно быть достаточно ясно, что происходит. Как упоминалось ранее, мы делаем здесь маршрутизацию на основе содержимого, то есть мы используем фактическую полезную нагрузку сообщения (т. Е. Экземпляр Lead ) для принятия решения о маршрутизации, а не с помощью заголовков сообщений. Эта способность проверять полезную нагрузку сообщений является ключевой, поскольку она позволяет нам перемещать «интеллектуальные возможности» системы в саму шину вместо того, чтобы заставлять клиентов предоставлять подсказки (например, в форме заголовков сообщений), которые направляют обработку в правильном направлении. Это снижает нагрузку на клиентов и делает автобус более удобным для использования.

Последний шаг — связать все это вместе в нашей конфигурации шины сообщений.

Обновите конфигурацию шины сообщений

В листинге 3 представлены некоторые обновления нашей шины сообщений.

Листинг 3. /WEB-INF/applicationContext-integration.xml обновления для поддержки ведущей маршрутизации

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:mail="http://www.springframework.org/schema/integration/mail"
xmlns:ws="http://www.springframework.org/schema/integration/ws"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
http://www.springframework.org/schema/integration/mail
http://www.springframework.org/schema/integration/mail/spring-integration-mail-1.0.xsd
http://www.springframework.org/schema/integration/ws
http://www.springframework.org/schema/integration/ws/spring-integration-ws-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">

<context:property-placeholder
location="classpath:applicationContext.properties" />

<gateway id="leadGateway"
service-interface="crm.integration.gateways.LeadGateway" />

<publish-subscribe-channel id="newLeadChannel" />

<router input-channel="newLeadChannel">
<beans:bean id="countryRouter"
class="crm.integration.routers.CountryRouter" />
</router>

<channel id="domesticChannel" />

<service-activator
input-channel="domesticChannel"
ref="leadService"
method="createLead" />

<channel id="internationalChannel" />

<util:list id="classesToBeBound">
<beans:value>crm.model.Lead</beans:value>
</util:list>

<beans:bean id="marshaller"
class="org.springframework.oxm.jaxb.Jaxb2Marshaller"
p:classesToBeBound-ref="classesToBeBound" />

<ws:outbound-gateway
request-channel="internationalChannel"
uri="${external.crm.uri}"
marshaller="marshaller" />

<transformer input-channel="newLeadChannel" output-channel="confEmailChannel">
<beans:bean class="crm.integration.transformers.LeadToEmailTransformer">
<beans:property name="confFrom" value="${conf.email.from}" />
<beans:property name="confSubject" value="${conf.email.subject}" />
<beans:property name="confText" value="${conf.email.text}" />
</beans:bean>
</transformer>

<channel id="confEmailChannel" />

<mail:outbound-channel-adapter
channel="confEmailChannel"
mail-sender="mailSender" />
</beans:beans>

Здесь происходит несколько вещей; поэтому мы возьмем их по очереди. Полезно взглянуть на рисунок 1, глядя на эту конфигурацию.

Во-первых, обратите внимание, что мы добавили объявления пространства имен util и ws и расположения схемы в элемент bean- элементов верхнего уровня . В WS префикс идентифицирует элементы схемы веб — служб Spring интеграции в.

Затем мы вставили маршрутизатор между newLeadChannel и активатором службы, который ранее был подключен к newLeadChannel . Мы определили bean- компонент CountryRouter как внутренний bean-компонент, чтобы скрыть его определение от остального контекста.

После маршрутизатора сообщения могут идти в одном из двух направлений, как мы уже обсуждали. Внутренняя ветвь — это то, что мы имели в конце предыдущего урока. Международная отрасль, однако, является новой. Существует международный канал, который подключается к исходящему шлюзу веб-службы SOAP. Мы должны предоставить шлюзу маршаллер (мы выбрали маршалер JAXB, хотя доступны и другие варианты), чтобы он мог превращать полезную нагрузку в сообщения SOAP, и в этом вся суть конфигурации маршаллера.

Вам также необходимо добавить следующее свойство в applicationContext.properties, чтобы указать URI для внешней CRM:

external.crm.uri = HTTP: // локальный: 9091 / xcrm / главная / leads.xml

 

 
Как только вы все это сделаете, запустите обе CRM, запустив

мвн причал: беги

 против POM соответствующего модуля. После этого попробуйте создать несколько потенциальных клиентов с помощью пользовательского интерфейса:

HTTP: // локальный: 8080 / CRM / главная / ведущий / form.html

Когда вы создаете внутреннее лидерство, оно должно идти в локальную CRM, а когда вы создаете международное лидерство, оно должно переходить во внешнюю CRM (где вы увидите сообщение SOAP, отображаемое в командной строке). В любом случае система отправит ведущему электронное письмо с подтверждением.

В следующих двух разделах будет показано, как интегрировать так называемые запросы на информацию (RFI), которые позволяют вести (да) информацию запроса. Сначала мы сделаем веб-форму RFI, а затем мы сделаем устаревшую RFI на основе электронной почты.


Интеграция веб-форм RFI

[Код для этого раздела доступен здесь ]

Запросы на информационные формы или RFI являются важной частью ведущей области управления. Они позволяют потенциальным клиентам узнать больше, и они приводят к созданию потенциальных клиентов в системе управления потенциальными клиентами. Квалифицированные представители или продавцы могут затем вывести лидерство из CRM и продолжить, предоставляя запрошенную информацию. В контексте нашего гипотетического онлайн-университета консультанты по зачислению могут, например, связаться с потенциальными студентами с информацией об академических программах, финансовой помощи и так далее.

На рисунке 2 показано, как наш веб-RFI вписывается в общую схему вещей.

Рисунок 2: Мы собираемся принимать от веб-форм RFI.

Давайте пройдемся по различным этапам, связанным с добавлением нового веб-интерфейса RFI к общей интеграции.

Добавить сайт ведущего поколения

Формы RFI размещаются на сайтах потенциальных клиентов, ориентированных на клиентов, поэтому нам понадобится отдельный модуль Maven. Смотрите код загрузки для свинцового модуля. Обычно это целый сайт, который описывает университетские мероприятия, академические программы, профили студентов и преподавателей, информацию об аккредитации и тому подобное. Здесь, хотя нас интересует только сама форма RFI, так что это все, что есть у нашего примера сайта.

Когда пользователь отправляет RFI, он переходит к веб-контроллеру MVC (часть сайта ведущего поколения), который, в свою очередь, передает его компоненту службы (все еще являющемуся частью сайта ведущего поколения). Служебный компонент использует HttpClient для отправки HTTP-запроса POST через брандмауэр в CRM, который обычно находится во внутренней сети. Таким образом, как показывает этот пример, мы можем интегрировать системы в DMZ с системами во внутренней сети.

Как только HTTP-запрос попадает на шину (и мы вскоре покажем, как это работает), у нас должен быть способ преобразовать его в объект Lead, который мы можем разместить в newLeadChannel . В следующем разделе показано, как это сделать.

Преобразовать параметры запроса HTTP POST в Lead

В первом уроке мы создали компонент-трансформер для преобразования Lead в MailMessage, чтобы мы могли отправлять потенциальным студентам электронное письмо с подтверждением. Здесь мы собираемся создать еще один компонент-трансформер, на этот раз для сопоставления HTTP-запроса POST с Lead . В листинге 4 показано, как это делается.

Мы уже рассмотрели механизм создания bean-компонента-трансформера, поэтому нет необходимости повторять это. В этом случае адаптер канала HTTP (мы увидим его на мгновение) создает сообщение с картой параметров HTTP в качестве полезной нагрузки, поэтому наш метод @Transformer принимает карту в качестве входных данных.

Последний шаг — еще раз настроить шину сообщений.

Настройте шину сообщений для добавления нового конвейера.

В applicationContext -gration.xml нет особых изменений , поэтому вместо отображения всей конфигурации список 5 концентрируется на изменяющихся частях.

Листинг 5. Обновление /WEB-INF/applicationContext-integration.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:http="http://www.springframework.org/schema/integration/http"

... other namespace declarations ...

xsi:schemaLocation="http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd

... other schema locations ...

http://www.springframework.org/schema/integration/http
http://www.springframework.org/schema/integration/http/spring-integration-http-1.0.xsd">

<beans:bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

<http:inbound-channel-adapter
name="/leads"
channel="httpLeadChannel"
supported-methods="POST"/>

<channel id="httpLeadChannel" />

<transformer input-channel="httpLeadChannel" output-channel="newLeadChannel">
<beans:bean class="crm.integration.transformers.HttpToLeadTransformer" />
</transformer>

... other message bus configuration ...

</beans:beans>

Мы добавили новое пространство имен http и расположение схемы и используем его для объявления адаптера входящего HTTP-канала, который обрабатывает запросы, поступающие в путь / lead , благодаря BeanNameUrlHandlerMapping . (См. Spring Web MVC, если вы не знаете, как это работает.) Полный URI

HTTP: // локальный: 8080 / CRM / основной / провод

и это целевой URI для запросов HTTP POST, которые отправляет HttpClient сайта ведущего поколения . Адаптер входящего канала прослушивает запросы HTTP POST, сопоставленные с этим URI, а затем помещает сообщение, содержащее карту параметров, в httpLeadChannel . Автобус берет на себя оттуда.

У нас есть определение трансформатора, но мы уже видели одно из них, поэтому мы не будем его освещать снова.

Чтобы попробовать это, запустите свой CRM и ведущий сайт и направьте свой браузер на

HTTP: // локальный: 9090 / leadgen / главная / RFI / form.html

Форма RFI в том виде, в каком она существует в настоящее время, не позволяет указать страну, поэтому страна будет нулевой, а все запросы RFI будут проходить через внутренний канал и попадать в местный CRM. Таким образом, вам не нужно запускать внешнюю CRM.

Еще один, прежде чем мы назовем это днем: RFI на основе электронной почты.


Интеграция устаревших RFI на основе электронной почты

[Код для этого раздела доступен здесь]

Последним элементом нашей интеграции станет унаследованный канал для RFI на основе электронной почты. Смотрите рисунок 3 ниже, который представляет конечный продукт.

  Рисунок 3: Конечный продукт: интегрированный модуль управления потенциальными клиентами.

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

ВНИМАНИЕ: ЭТО УДАЛЕТ ВСЕ СООБЩЕНИЯ В ВАШЕ ПОЧТУ! НЕ используйте свою личную учетную запись электронной почты, если вы не возражаете против удаления всех ваших сообщений!

Я усвоил этот урок, думая, что, поскольку это почтовый ящик IMAP, почта останется на сервере. Именно так работает IMAP, но это не IMAP, пожирающий электронные письма. Это Spring Integration (и это по замыслу). Во всяком случае, вы были предупреждены!

Вот изменения, которые нам нужно сделать.

Обновите Lead.java для поддержки заметок

Во-первых, поскольку электронная почта в основном неструктурирована, нам понадобится способ получить то, что хочет сказать потенциальный студент. Поэтому мы добавим свойство notes в Lead.java . Кроме того, мы добавим метод для извлечения имени и фамилии из полного имени отправителя. Смотрите листинг 6 ниже.

Листинг 6. Обновления в Lead.java

 

package crm.model;

import java.util.List;
import org.springframework.util.StringUtils;

... various imports ...

... same annotations as before ...
public class Lead {
private List<String> notes;

... various fields and methods ...

@XmlTransient
public List<String> getNotes() { return notes; }

public void setNotes(List<String> notes) { this.notes = notes; }

public void guessNamesFromFullName(String fullName) {
if (fullName == null) { return; }
String[] tokens = fullName.trim().split("\\s+");
int len = tokens.length;
if (len == 0) {
return;
} else if (len == 1) {
if (!tokens[0].equals("")) { setFirstName(tokens[0]); }
} else {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < len - 1; i++) {
builder.append(tokens[i] + " ");
}
setFirstName(builder.toString().trim());
setLastName(tokens[len - 1]);
}
}

... minor toString() update (see code download) ...
}

 

В методе guessNamesFromFullName () достаточно логики для проведения модульного теста, а пример кода включает в себя модульный тест, охватывающий этот метод.

Нам нужно превратить электронную почту в потенциальных клиентов, и мы посмотрим на это сейчас.

Создать EmailToLeadTransformer.java

В листинге 7 приведен компонент-трансформер для преобразования электронной почты в потенциальных клиентов.

Листинг 7. EmailToLeadTransformer.java

 

 

package crm.integration.transformers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.springframework.integration.annotation.Transformer;
import crm.model.Lead;

public class EmailToLeadTransformer {
private static Logger log = Logger.getLogger("global");

@Transformer
public Lead transform(MimeMessage email) {
log.info("Transforming e-mail to lead");
try {
InternetAddress from = (InternetAddress) email.getFrom()[0];
String fullName = from.getPersonal();

Lead lead = new Lead();
lead.guessNamesFromFullName(fullName);
lead.setEmail(from.getAddress());
lead.setDateCreated(email.getSentDate());

StringBuilder builder = new StringBuilder("Full name: " + fullName);
builder.append("\nSubject: " + email.getSubject());

// FIXME Doesn't work with MimeMultipart. Output looks like this:
// javax.mail.internet.MimeMultipart@598d00
builder.append("\n\n" + email.getContent().toString());

List<String> notes = new ArrayList<String>();
notes.add(builder.toString());
lead.setNotes(notes);

log.info("Transformed e-mail to lead: " + lead);
return lead;
} catch (MessagingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

 

 

Код в листинге 7 не соответствует промышленному уровню: он, например, не обрабатывает общий случай составных электронных писем. Мы можем назвать это упражнение, оставленное читателю. (Ха-ха.) Но в нем есть основы извлечения имени, адреса электронной почты, даты, темы и даже тела, если вы не отправляете многочастное электронное письмо.

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

3.3 Получение сообщений электронной почты на шину сообщений

Существует как минимум три разных варианта получения сообщений электронной почты на шину сообщений:

Мы собираемся сделать третий, так как легко получить почтовый ящик IMAP, который поддерживает IDLE (например, Gmail). Для этого нам потребуется обновить нашу конфигурацию несколькими способами. Сначала нам нужно создать файл imap.properties с соответствующей конфигурацией почтового ящика. Смотрите пример файла в /crm/src/resources/imap.properties.sample для примера.

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

ХОРОШО. В листинге 8 показаны обновления, которые мы должны внести в applicationContext -gration.xml .

Листинг 8. Обновление /WEB-INF/applicationContext-integration.xml .

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
... various namespace and schema location declarations ... >

<!-- Note: This requires Spring Integration 1.0.3 or higher. -->
<context:property-placeholder location="classpath:*.properties" />

<!-- Use this if your server supports IMAP IDLE. Requires JavaMail 1.4.1
or higher on the client side. -->
<mail:imap-idle-channel-adapter
channel="emailLeadChannel"
store-uri="${email.store.uri}"
should-delete-messages="true" />

<!-- Use this if your server doesn't support IMAP IDLE. -->
<!--
<mail:inbound-channel-adapter
channel="emailLeadChannel"
store-uri="${email.store.uri}">
<poller max-messages-per-poll="3">
<interval-trigger interval="30" time-unit="SECONDS" />
</poller>
</mail:inbound-channel-adapter>
-->

<channel id="emailLeadChannel" />

<transformer input-channel="emailLeadChannel" output-channel="newLeadChannel">
<!-- Use inner bean instead of ref because no one else uses this bean -->
<beans:bean class="crm.integration.transformers.EmailToLeadTransformer" />
</transformer>

... other stuff ...

</beans:beans>

Изменение в части заполнителя свойства состоит в том, что теперь у нас есть два файла свойств для загрузки вместо одного. (Напомним, что мы только что добавили imap.properties .)

Более существенным изменением является добавление адаптера канала IMAP IDLE, который в основном настраивает шину сообщений для прослушивания уведомлений по электронной почте из почтового ящика IMAP. Я включил must-delete-messages = «true»приписывать здесь только для того, чтобы подчеркнуть его существование; однако это не является необходимым, поскольку значение по умолчанию — true. (Кроме того, я не уверен, что мне нравится, что значение по умолчанию равно true. Я понимаю, что это должно быть так, если мы хотим использовать почтовый ящик в качестве очереди сообщений, но, черт возьми, обидно случайно удалить четыре или пять электронной почты, которую вы сохранили за многие годы. Я мог бы предложить команде Spring Integration полностью удалить значение по умолчанию и сделать этот атрибут обязательным. В любом случае.) Если ваш почтовый ящик не поддерживает IDLE, вы можете использовать альтернативный конфигурация адаптера, которая опрашивает интервал, который вы можете установить. И опять же, есть адаптер POP3, если вы этого хотите.

Остальное это то, что мы уже видели.

После того, как все будет готово, запустите приложение CRM и отправьте электронное письмо на указанный вами почтовый ящик IMAP. Вы должны получить подтверждение по электронной почте вскоре после этого.

Резюме

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

Автобус, который мы строим, действительно только отправная точка. Помимо компонентов маршрутизатора, трансформатора, шлюза, канала и канального адаптера, которые мы здесь видели, есть еще несколько других, которые мы не рассмотрели, в том числе:

  • Фильтр: решить, следует ли удалить сообщение

  • Разделитель: разделить сообщение на несколько сообщений

  • Агрегатор: сведение нескольких сообщений в одно сообщение

  • Resequencer: заказывает группу сообщений

  • Delayer: задерживает распространение сообщений

  • Цепочка обработчика сообщений: обеспечивает удобный способ упорядочения последовательности конечных точек

  • Messaging Bridge: подключите два канала или канальные адаптеры

В дополнение к вышеперечисленным компонентам есть несколько шлюзов и канальных адаптеров, которые вы можете изучить самостоятельно, в том числе для

  • Поддержка файлов

  • Поддержка JMS

  • Поддержка веб-сервисов (как входящих, так и исходящих)

  • Поддержка RMI

  • Поддержка HttpInvoker

  • Поддержка потока

  • …и более

Излишне говорить, что здесь есть много возможностей, и со временем я ожидаю увидеть больше шаблонов из Enterprise Integration Patterns, попадающих в структуру.

Некоторые другие фреймворки / платформы, которые могут вас заинтересовать:

До следующей встречи!

Вилли — архитектор решений с 12-летним опытом разработки Java. Он и его брат Джон являются соавторами готовящейся к публикации книги «Весна на практике» от Manning Publications ( www.manning.com/wheeler/ ). Вилли также публикует технические статьи (в том числе много о Spring) по адресу wheelersoftware.com/articles/ .

Не забывайте свой код ваучера, dzone30, если вы покупаете книгу.

Если вам понравилась эта статья, вам понравится первая часть серии, а также другая статья Вилли, посвященная Spring Batch .