Интеграция Spring для клиента TCP Socket с использованием динамического хоста и порта

#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 . Не могли бы вы, пожалуйста, добавить полный рабочий фрагмент?