Первая сессия была простым приложением Hello World, использующим Spring Integration. Я хочу пойти немного дальше, рассмотрев еще несколько сценариев вокруг этого.
Итак, первое изменение в приложении Hello World — добавить компонент Gateway. Чтобы быстро вернуться к предыдущей тестовой программе:
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
|
package org.bk.si.helloworld.hw1; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.message.GenericMessage; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith (SpringJUnit4ClassRunner. class ) @ContextConfiguration ( "helloworld.xml" ) public class HelloWorldTest { @Autowired @Qualifier ( "messageChannel" ) MessageChannel messageChannel; @Test public void testHelloWorld() { Message<String> helloWorld = new GenericMessage<String>( "Hello World" ); messageChannel.send(helloWorld); } } |
В выделенных выше строках тест зависит от конкретного компонента Spring Integration — канала сообщений, а в тесте создается явное сообщение интеграции Spring и отправляется в канал сообщений. Слишком тесная связь с Spring Integration, которая здесь является системой обмена сообщениями.
Компонент Gateway обеспечивает фасад для системы обмена сообщениями, защищая пользовательское приложение (в данном случае модульное тестирование) от деталей системы обмена сообщениями — канала обмена сообщениями, Message и явной отправки сообщения.
Сначала приведем пример того, как будет выглядеть тест с компонентом Gateway:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package org.bk.si.helloworld.hw2; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith (SpringJUnit4ClassRunner. class ) @ContextConfiguration ( "helloworld.xml" ) public class HelloWorldTest { @Autowired Greeter greeter; @Test public void testHelloWorld(){ this .greeter.sendGreeting( "Hello World" ); } } |
Приведенный выше интерфейс Greeter является компонентом Gateway. Теперь, когда этот компонент был представлен, в этом тесте нет зависимости от Spring Integration — в коде вообще не упоминается Message, Message Channel.
Компонент Gateway также является очень простым Java-интерфейсом, определенным следующим образом:
1
2
3
4
5
|
package org.bk.si.helloworld.hw2; public interface Greeter { public void sendGreeting(String message); } |
Итак, теперь вопрос в том, кто позаботится о создании сообщений и отправке сообщений в канал сообщений — это через конфигурацию Spring Integration:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> < int:channel id = "messagesChannel" ></ int:channel > < int:gateway service-interface = "org.bk.si.helloworld.hw2.Greeter" default-request-channel = "messagesChannel" ></ int:gateway > < int-stream:stdout-channel-adapter channel = "messagesChannel" append-newline = "true" /> </ beans > |
Выделенная строка выше создает компонент Gateway из интерфейса Greeter, в фоновом режиме создается прокси-сервер, который обрабатывает все, что было сделано ранее — создание сообщений и отправка сообщений в канал сообщений.
Теперь добавим немного большей сложности к примеру Hello World:
Рассмотрим следующий тест:
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
|
package org.bk.si.helloworld.hw3; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith (SpringJUnit4ClassRunner. class ) @ContextConfiguration ( "helloworld.xml" ) public class HelloWorldTest { @Autowired Greeter greeter; @Test public void testHelloWorld(){ System.out.println( "Started.." ); long start = System.nanoTime(); for ( int i= 0 ;i< 10 ;i++){ this .greeter.sendMessage(String.format( "Hello World %d" ,i)); } System.out.println( "Completed.." ); System.out.println(String.format( "Took %f ms" , (System.nanoTime()-start)/10e6)); } } |
Это то же самое, что и предыдущий модульный тест, за исключением того, что в этом случае сообщение «Hello World» отправляется 10 раз. Поддерживающий конфигурационный файл Spring Integration:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> < int:publish-subscribe-channel id = "messagesChannel" /> < int:gateway service-interface = "org.bk.si.helloworld.hw3.Greeter" default-request-channel = "messagesChannel" ></ int:gateway > < int-stream:stderr-channel-adapter channel = "messagesChannel" append-newline = "true" /> < int-stream:stdout-channel-adapter channel = "messagesChannel" append-newline = "true" /> </ beans > |
Если я сейчас запущу этот тест, результат будет таким:
Красные линии печатаются в syserr, а черные печатаются в sysout.
Итак, вопрос в том, почему некоторые из них собираются на sysout, а некоторые — на syserr, а почему нет — на оба?
Ответ из-за типа канала — «messagesChannel» выше является «Прямым каналом» в терминологии Spring Integration и имеет семантику «точка-точка». Семантика точка-точка в основном означает, что когда сообщение поступает в канал обмена сообщениями, только 1 получатель получает сообщение — так что в этом случае либо стандартный выходной адаптер, либо стандартный адаптер ошибки заканчивает тем, что печатает сообщение, поступающее в Канал сообщений.
Таким образом, для печати на обоих адаптерах необходимо просто изменить семантику канала — вместо канала «точка-точка» сделать его каналом публикации-подписки, который является каналом, передающим сообщение нескольким получателям. Изменение очень просто с помощью Spring Integration:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
file:/C:/learn/scratch/target/test-classes/org/bk/htmlencode/content.txt <? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-2.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> < int:publish-subscribe-channel id = "messagesChannel" /> < int:gateway service-interface = "org.bk.si.helloworld.hw3.Greeter" default-request-channel = "messagesChannel" ></ int:gateway > < int-stream:stderr-channel-adapter channel = "messagesChannel" append-newline = "true" /> < int-stream:stdout-channel-adapter channel = "messagesChannel" append-newline = "true" /> </ beans > |
Теперь выводом будут сообщения, которые печатаются в ОБА sysout и syserr
Таким образом, на этом заканчивается введение в компонент шлюза, прямой канал и канал публикации подписки.
Ссылка: Spring Integration — Сессия 2 — Больше Hello Worlds от нашего партнера JCG Биджу Кунджуммен в блоге all and sundry.