#spring-boot #spring-integration #tcpsocket
#весенняя загрузка #spring-интеграция #tcpsocket
Вопрос:
У меня есть рабочий пример TCPSocketClient, использующий интеграцию Spring с жестко закодированным именем хоста и портом.
Как изменить этот пример, чтобы принять localhost
и порт 5877
, которые будут передаваться динамически?
т.е. Возможно ли вызвать метод exchange, подобный ExchangeService.exchange(hostname, port, request)
вместо ExchangeService.exchange(request)
Если да, то как эти параметры применяются к client
компоненту?
@Configuration
public class AppConfig {
@Bean
public IntegrationFlow client() {
return IntegrationFlows.from(ApiGateway.class).handle(
Tcp.outboundGateway(
Tcp.netClient("localhost", 5877)
.serializer(codec())
.deserializer(codec())
).remoteTimeout(10000)
)
.transform(Transformers.objectToString())
.get();
}
@Bean
public ByteArrayCrLfSerializer codec() {
ByteArrayCrLfSerializer crLfSerializer = new ByteArrayCrLfSerializer();
crLfSerializer.setMaxMessageSize(204800000);
return crLfSerializer;
}
@Bean
@DependsOn("client")
public ExchangeService exchangeService(ApiGateway apiGateway) {
return new ExchangeServiceImpl(apiGateway);
}
}
public interface ApiGateway {
String exchange(String out);
}
public interface ExchangeService {
public String exchange(String request);
}
@Service
public class ExchangeServiceImpl implements ExchangeService {
private ApiGateway apiGateway;
@Autowired
public ExchangeServiceImpl(ApiGateway apiGateway) {
this.apiGateway=apiGateway;
}
@Override
public String exchange(String request) {
String response = null;
try {
response = apiGateway.exchange(request);
} catch (Exception e) {
throw e;
}
return response;
}
}
Ответ №1:
Для динамической обработки вы можете рассмотреть возможность использования функции динамических потоков из Spring Integration Java DSL: https://docs.spring.io/spring-integration/docs/current/reference/html/#java-dsl-runtime-flows
Итак, всякий раз, когда вы получаете запрос с этими параметрами, вы создаете IntegrationFlow
«на лету» и регистрируете его в IntegrationFlowContext
. Честно говоря, у нас есть точный пример в документах для вашего варианта использования TCP:
IntegrationFlow flow = f -> f
.handle(Tcp.outboundGateway(Tcp.netClient("localhost", this.server1.getPort())
.serializer(TcpCodecs.crlf())
.deserializer(TcpCodecs.lengthHeader1())
.id("client1"))
.remoteTimeout(m -> 5000))
.transform(Transformers.objectToString());
IntegrationFlowRegistration theFlow = this.flowContext.registration(flow).register();
Комментарии:
1. Я могу подключить api, но у меня есть проблема с этим подходом. При первом вызове я получаю правильный ответ. и когда я отправляю второй запрос, я получаю исключение, подобное
BeanDefinitionOverrideException: Invalid bean definition with name 'client1' defined in the 'com.sakthi.springintegration.tcpclient.config.ExchangeServiceImpl$$Lambda$394/810619513#1' bean definition: Cannot register bean definition [Generic bean: class [org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory]; scope=; abstract=false; lazyInit=false; autowireMode=0; ...
2. Вам следует рассмотреть возможность удаления этих динамических потоков после использования или кэширования их хостом / портом для последующих запросов
3. У меня есть частный метод в моем,
ExchangeServiceImpl
который содержит приведенный выше фрагмент и будет возвращать егоtheFlow
каждый раз. Используя это, я вызываюtheFlow.getMessagingTemplate().convertSendAndReceive("foo", String.class)
для каждого запроса. Правильный ли мой подход? т. Е. я автоматически подключил ExchangeServiceImpl и вызываю метод exchange, который выполнит это convertsendиreceive. Сейчас все работает нормально.4. Да! Все в порядке. Или вы можете включить это в
@MessagingGateway
интерфейс.5. Привет, Артем Билан, я автоматически подключил этот ExchangeServiceImpl к контроллеру и отправил 2 запроса один за другим. Получение того же исключения. Первый запрос выполнен успешно, а второй запрос выдает исключение, подобное
bean definition: Cannot register bean definition [Generic bean: class [org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory] defined in the ExchangeServiceImpl$$Lambda$395/1233672433#1 for bean 'client1': There is already TcpNetClientConnectionFactory bound
. Не могли бы вы, пожалуйста, добавить полный рабочий фрагмент?