Java 如何在SpringCloudStream中配置函数的绑定,将其输入绑定到web端点,将其输出绑定到Kafka主题

Java 如何在SpringCloudStream中配置函数的绑定,将其输入绑定到web端点,将其输出绑定到Kafka主题,java,spring-boot,java-8,spring-cloud,functional-interface,Java,Spring Boot,Java 8,Spring Cloud,Functional Interface,我有一个常规的java函数;我正试图将其绑定: 将其输入到web端点 将其输出为卡夫卡主题 当我在web上下文中使用我的函数时,它总是将函数的结果值单独返回给web客户端。我可以这样做吗 spring.cloud.stream.bindings.input.binder=web spring.cloud.stream.bindings.output.binder=kafka 我目前甚至正在尝试将函数分为两部分: 其输入绑定到web客户端,其输出动态绑定到第二个函数(使用spring.clou

我有一个常规的java
函数
;我正试图将其绑定:

  • 将其输入到web端点
  • 将其输出为卡夫卡主题 当我在web上下文中使用我的函数时,它总是将
    函数的结果值
    单独返回给web客户端。我可以这样做吗

    spring.cloud.stream.bindings.input.binder=web
    spring.cloud.stream.bindings.output.binder=kafka
    
    我目前甚至正在尝试将
    函数
    分为两部分:

    • 其输入绑定到web客户端,其输出动态绑定到第二个函数(使用
      spring.cloud.stream.sendto.destination
    • 另一个函数,其输出绑定到kafka绑定
    但这种方法也不起作用。动态路由(
    spring.cloud.stream.sendto.destination
    )显示在web客户端上;但是没有
    消息
    发送到卡夫卡绑定本身。下面是我在第二种方法(2个函数)中使用的代码,希望得到一个Spring函数应用程序,将其输入绑定到web端点,并将输出绑定到kafka主题

    WebToKafkaApp.java

    @SpringBootApplication
    public class WebToKafkaApp {
        public static void main(String[] args) {
            SpringApplication.run(WebToKafkaApp.class, args);
        }
    
        @Bean
        public Function<String, Message<String>> webFunction() {
            return payload -> createPayloadMapperToMessage("kafkaFunction").apply(payload);
        }
    
        @Bean
        public Function<Flux<Message<String>>, Flux<Message<String>>> kafkaFunction() {
            return flux -> flux.map(msg -> createPayloadMapperToMessage("").apply(msg.getPayload()));
        }
    
        private Function<String, Message<String>> createPayloadMapperToMessage(String destination) {
            return payload -> MessageBuilder
                    .withPayload(payload.toUpperCase())
                    .setHeader("spring.cloud.stream.sendto.destination", destination)
                    .build();
        }
    }
    
    build.gradle

    plugins {
        id 'org.springframework.boot' version '2.2.1.RELEASE'
        id 'io.spring.dependency-management' version '1.0.8.RELEASE'
        id 'java'
    }
    group = 'com.example'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '1.8'
    repositories {
        mavenCentral()
    }
    ext {
        set('springCloudVersion', "Hoxton.RELEASE")
    }
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter'
        implementation 'org.springframework.cloud:spring-cloud-starter-function-web'
        implementation 'org.springframework.cloud:spring-cloud-starter-function-webflux'
        implementation 'org.springframework.cloud:spring-cloud-stream'
        implementation 'org.springframework.cloud:spring-cloud-starter-stream-kafka'
        testImplementation('org.springframework.boot:spring-boot-starter-test') {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        }
    }
    dependencyManagement {
        imports {
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        }
    }
    test {
        useJUnitPlatform()
    }
    
    任何帮助都将不胜感激。

    感谢您的发布。基本上,我强化了他的建议,即一般性地处理以下两者之间的桥梁:

  • 功能性web控制器;它可以接收web请求
  • 流供应商;它可以将任何消息转发到消息传递基础结构
  • 此解决方案将中描述的问题封装在
    供应商的自定义实现中。这样的实现公开了一个API来触发供应商发出作为参数传递的消息。这样的类将如下所示:

    import org.springframework.messaging.Message;
    import org.springframework.messaging.support.MessageBuilder;
    
    import java.util.function.Supplier;
    
    import reactor.core.publisher.EmitterProcessor;
    import reactor.core.publisher.Flux;
    
    public class StreamSupplier implements Supplier<Flux<?>> {
    
        private static final String SPRING_CLOUD_STREAM_SENDTO_DESTINATION =
                "spring.cloud.stream.sendto.destination";
    
        public static <T> Message<?> createMessage(T payload, String destination) {
            MessageBuilder<T> builder = MessageBuilder.withPayload(payload);
            if (destination != null && !destination.isEmpty())
                builder.setHeader(SPRING_CLOUD_STREAM_SENDTO_DESTINATION, destination);
            return builder.build();
        }
    
        private String defaultDestination;
        private EmitterProcessor<? super Object> processor = EmitterProcessor.create();
    
        public StreamSupplier() {
            this(null);
        }
    
        public StreamSupplier(String defaultDestination) {
            this.defaultDestination = defaultDestination;
        }
    
        // SEND APIs
    
        public <T> Message<?> sendMessage(T payload) {
            return sendMessage(payload, defaultDestination);
        }
    
        public <T> Message<?> sendMessage(T payload, String destination) {
            return sendBody(createMessage(payload, destination));
        }
    
        public <T> T sendBody(T body) {
            processor.onNext(body);
            return body;
        }
    
        /**
         * Returns {@link EmitterProcessor} used internally to programmatically publish messages onto
         * the output binding associated with this {@link Supplier}. Such programmatic publications
         * are available through the {@code sendXXX} API methods available in this class.
         */
        @Override
        public Flux<?> get() {
            return processor;
        }
    }
    
    再次感谢您为我提供了构建此综合解决方案所需的资源


    请在感谢@OlegZhurakousky为我指明了正确的方向中查看答案。我只是通过在您的细节之上构建额外的抽象级别来回答我的问题。
    import org.springframework.messaging.Message;
    import org.springframework.messaging.support.MessageBuilder;
    
    import java.util.function.Supplier;
    
    import reactor.core.publisher.EmitterProcessor;
    import reactor.core.publisher.Flux;
    
    public class StreamSupplier implements Supplier<Flux<?>> {
    
        private static final String SPRING_CLOUD_STREAM_SENDTO_DESTINATION =
                "spring.cloud.stream.sendto.destination";
    
        public static <T> Message<?> createMessage(T payload, String destination) {
            MessageBuilder<T> builder = MessageBuilder.withPayload(payload);
            if (destination != null && !destination.isEmpty())
                builder.setHeader(SPRING_CLOUD_STREAM_SENDTO_DESTINATION, destination);
            return builder.build();
        }
    
        private String defaultDestination;
        private EmitterProcessor<? super Object> processor = EmitterProcessor.create();
    
        public StreamSupplier() {
            this(null);
        }
    
        public StreamSupplier(String defaultDestination) {
            this.defaultDestination = defaultDestination;
        }
    
        // SEND APIs
    
        public <T> Message<?> sendMessage(T payload) {
            return sendMessage(payload, defaultDestination);
        }
    
        public <T> Message<?> sendMessage(T payload, String destination) {
            return sendBody(createMessage(payload, destination));
        }
    
        public <T> T sendBody(T body) {
            processor.onNext(body);
            return body;
        }
    
        /**
         * Returns {@link EmitterProcessor} used internally to programmatically publish messages onto
         * the output binding associated with this {@link Supplier}. Such programmatic publications
         * are available through the {@code sendXXX} API methods available in this class.
         */
        @Override
        public Flux<?> get() {
            return processor;
        }
    }
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Controller;
    
    import java.util.function.Function;
    import java.util.function.Supplier;
    
    import reactor.core.publisher.Flux;
    
    @SpringBootApplication
    @Controller
    public class MyApp {
    
        public static void main(String[] args) {
            SpringApplication.run(MyApp.class,
                    "--spring.cloud.function.definition=streamSupplierFunction;webToStreamFunction");
        }
    
        // Functional Web Controller
        @Bean
        public Function<String, String> webToStreamFunction() {
            return msg -> streamSupplier().sendBody(msg);
        }
    
        // Functional Stream Supplier
        @Bean
        public Supplier<Flux<?>> streamSupplierFunction() {
            return new StreamSupplier();
        }
    
        // DOUBLE REGISTRATION TO AVOID POLLABLE CONFIGURATION
        // LIMITATION OF SPRING-CLOUD-FUNCTION
        @Bean
        public StreamSupplier streamSupplier() {
            return (StreamSupplier) streamSupplierFunction();
        }
    }