#spring-integration
#spring-интеграция
Вопрос:
После использования Spring Integration в проекте я считаю, что следует использовать адаптер или шлюз jdbc только в начале или в конце потока. Если мы будем использовать их в середине потока, то он станет слишком подробным и сложным.
Например:
<jdbc:outbound-gateway
query="select * from foo where
c1=:headers[c1] AND
c2=:headers[c2] AND
c3=:headers[c3] AND
c4=:headers[c4]"
row-mapper="fooMapper" data-source="myDataSource" max-rows-per-poll="100000" />
<int:service-activator ref="serviceActivator" method="processFoo" />
В приведенном выше <jdbc:outbound-gateway>
примере нам нужно передать все заполнители (c1, c2, c3, c4) в заголовке сообщения. Нам нужно просматривать java-код и XML-файл для любых изменений в where условие или когда слишком много предложений where.
Это также подвержено ошибкам. Например, если мы неправильно :headers[c1]
написали to :headers[d1]
, то он не выдаст никакого исключения и заменит :headers[d1]
на null
.
Если запрос не возвращает ни одной строки, то по умолчанию он будет генерировать исключение. Итак, мы должны использовать requires-reply="false"
его, чтобы изменить поведение по умолчанию.
Если мы хотим продолжить, когда запрос не возвращает никакого значения, тогда мы должны добавить рекомендации в gateway, как показано ниже:
<jdbc:outbound-gateway ... >
<jdbc:request-handler-advice-chain>
<bean class="com.service.NullReplyAdvice" />
</jdbc:request-handler-advice-chain>
</jdbc:outbound-gateway>
Пожалуйста, поправьте меня, если есть недостатки в понимании концепции.
Ответ №1:
Нам нужно просматривать java-код и XML-файл на предмет любых изменений в условии where или когда предложений where слишком много.
Это верно даже для необработанного Java-кода вокруг JDBC: если вы измените модель, вы, конечно, должны изменить SELECT
, потому что это просто строка. И именно поэтому требуется много работы, чтобы сделать его типобезопасным — ORM, QueryDSL, Spring-Data и т.д.
если мы неправильно написали :headers[c1] в :headers[d1], то это не вызовет никаких исключений и заменит :headers[d1] на null .
Это потому headers
, что это просто a Map
, и это правда, которую вы получаете null
, если на карте такого a нет key
. Чтобы устранить эту проблему с опечаткой, вы можете использовать POJO payload
с геттерами или какой-нибудь пользовательский заголовок, и снова — POJO с геттерами. В этом случае вы получаете исключение из-за отсутствия такого свойства для object. Хотя вы увидите эту проблему только во время выполнения, а не при компиляции. И снова то же самое с Hashtable
— только во время выполнения.
Итак, мы должны использовать requires-reply=»false», чтобы изменить поведение по умолчанию.
Вы должны понимать это во время разработки: разрешить или не возвращать ничего для компонента.
Последняя идея хороша. Не могли бы вы поделиться своим NullReplyAdvice
? На самом деле я добиваюсь того же с <filter>
помощью шлюза before the JDBC: чтобы определить, есть ли что-то, что можно получить с помощью count(*)
запроса. Оттуда я могу привести свой поток к другой логике, а не к прямому потоку, когда SELECT
возвращает строки.
Обновить
Если вы хотите использовать объект модели для сохранения значений, специфичных для бизнеса, в сообщении, достаточно просто поместить этот объект в заголовок:
public class Foo {
private String foo1;
private String foo2;
public String getFoo1() {
return foo1;
}
public String getFoo2() {
return foo2;
}
}
...
MessageBuilder.withPayload(payload).setHeader("foo", foo).build();
...
<jdbc:outbound-gateway
query="select * from foo where
c1=:headers[foo].foo1 AND
c1=:headers[foo].foo2"/>
Комментарии:
1. Для реализации NullReplyAdvice, пожалуйста, проверьте forum.spring.io/forum/spring-projects/integration /…
2. В моем проекте слишком много запросов, и теперь он стал слишком подробным. Я должен использовать NullReplyAdvice после каждого запроса для обработки нулевых результатов. Не могли бы вы поделиться кодом полезной нагрузки POJO с получателями. Я попробую. Спасибо.
3. Добавлен образец заголовка POJO
4. В приведенном выше примере заголовка POJO показано, как выполнить маршрутизацию на основе значения [foo].foo1 . Например, что-то вроде этого: <int:header-value-router input-channel=»routingChannel» header-name=»:headers[foo].foo1″> <int:значение сопоставления =»X» channel=»xChannel» /> <int: значение сопоставления =»Y» channel=»yChannel» /> </int:заголовок-значение-маршрутизатор>
5. Нет, <заголовок-значение-маршрутизатор> просто извлекается
header
по указанному имени. Для этой вложенной цели вы должны использовать универсальный маршрутизатор с.expression="headers[foo].foo1"
:
Индикатор примечания предназначен только для JdbcTemplate