Java 如何从Http集成流创建Spring反应堆流量?

Java 如何从Http集成流创建Spring反应堆流量?,java,spring,spring-integration,reactive-programming,project-reactor,Java,Spring,Spring Integration,Reactive Programming,Project Reactor,我有一个和这个问题很相似的问题 一个区别是消息来自Http端点而不是JMS队列。问题是消息通道由于某种原因没有被填充,或者它没有被Flux.from()拾取。日志条目显示,GenericMessage是从Http集成流创建的,有效负载作为路径变量,但不会进入队列/发布到通道?我尝试了.channel(MessageChannels.queue())和.channel(MessageChannels.publishSubscribe()) 没有任何区别,事件流为空。代码如下: @Bean publ

我有一个和这个问题很相似的问题

一个区别是消息来自Http端点而不是JMS队列。问题是消息通道由于某种原因没有被填充,或者它没有被Flux.from()拾取。日志条目显示,GenericMessage是从Http集成流创建的,有效负载作为路径变量,但不会进入队列/发布到通道?我尝试了
.channel(MessageChannels.queue())
.channel(MessageChannels.publishSubscribe())
没有任何区别,事件流为空。代码如下:

@Bean
public Publisher<Message<String>> httpReactiveSource() {
        return IntegrationFlows.
                from(Http.inboundChannelAdapter("/eventmessage/{id}")
                        .requestMapping(r -> r
                        .methods(HttpMethod.POST)                                                                                   
                        )
                        .payloadExpression("#pathVariables.id")
                        )                           
                        .channel(MessageChannels.queue())
                        .log(LoggingHandler.Level.DEBUG)                            
                        .log()  
                        .toReactivePublisher();
    }


@GetMapping(value="eventmessagechannel/{id}", produces=MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> eventMessages(@PathVariable String id){     
    return Flux.from(httpReactiveSource())              
            .map(Message::getPayload);

}
更新2

@SpringBootApplication
@RestController
在一个文件中定义时,它工作,但当
@SpringBootApplication
@RestController
在单独的文件中时,它停止工作

TestApp.java

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class TestApp {
     public static void main(String[] args) {
            SpringApplication.run(TestApp.class, args);
    }
}
TestController.java

package com.example.controller;


import org.springframework.context.annotation.Bean;
import org.reactivestreams.Publisher;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.channel.MessageChannels;
import org.springframework.integration.handler.LoggingHandler;
import org.springframework.integration.http.dsl.Http;
import org.springframework.messaging.Message;
import org.springframework.web.bind.annotation.RestController;



import org.springframework.web.bind.annotation.GetMapping;
import reactor.core.publisher.Flux;



@RestController
public class TestController {
     @Bean
        public Publisher<Message<String>> httpReactiveSource() {
            return IntegrationFlows.
                    from(Http.inboundChannelAdapter("/message/{id}")
                            .requestMapping(r -> r
                                    .methods(HttpMethod.POST)
                            )
                            .payloadExpression("#pathVariables.id")
                    )
                    .channel(MessageChannels.queue())
                    .toReactivePublisher();
        }

        @GetMapping(value = "/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
        public Flux<String> eventMessages() {
            return Flux.from(httpReactiveSource())
                    .map(Message::getPayload);
        }

}
package com.example.controller;
导入org.springframework.context.annotation.Bean;
导入org.reactivestreams.Publisher;
导入org.springframework.http.HttpMethod;
导入org.springframework.http.MediaType;
导入org.springframework.integration.dsl.IntegrationFlows;
导入org.springframework.integration.dsl.channel.MessageChannels;
导入org.springframework.integration.handler.LoggingHandler;
导入org.springframework.integration.http.dsl.http;
导入org.springframework.messaging.Message;
导入org.springframework.web.bind.annotation.RestController;
导入org.springframework.web.bind.annotation.GetMapping;
导入reactor.core.publisher.Flux;
@RestController
公共类测试控制器{
@豆子
公共发布服务器httpReactiveSource(){
返回集成流。
来自(Http.inboundChannelAdapter(“/message/{id}”)
.requestMapping(r->r
.方法(HttpMethod.POST)
)
.payloadExpression(“#pathVariables.id”)
)
.channel(MessageChannels.queue())
.toReactivePublisher();
}
@GetMapping(value=“/events”,products=MediaType.TEXT\u EVENT\u STREAM\u value)
公共信息{
从(httpReactiveSource())返回通量
.map(消息::getPayload);
}
}

这对我很有效:

@SpringBootApplication
@RestController
public class SpringIntegrationSseDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringIntegrationSseDemoApplication.class, args);
    }

    @Bean
    public Publisher<Message<String>> httpReactiveSource() {
        return IntegrationFlows.
                from(Http.inboundChannelAdapter("/message/{id}")
                        .requestMapping(r -> r
                                .methods(HttpMethod.POST)
                        )
                        .payloadExpression("#pathVariables.id")
                )
                .channel(MessageChannels.queue())
                .toReactivePublisher();
    }

    @GetMapping(value = "/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> eventMessages() {
        return Flux.from(httpReactiveSource())
                .map(Message::getPayload);
    }

}
听她说话

在第二个例子中,我这样做:

curl -X POST http://localhost:8080/message/foo

curl -X POST http://localhost:8080/message/bar

curl -X POST http://localhost:8080/message/666
因此,第一个终端响应如下:

data:foo

data:bar

data:666
注意,我们不需要
springbootstarterwebflux
依赖项。SSE的
Flux
与Servlet容器上的常规MVC配合良好

Spring集成也将很快支持WebFlux:。因此,您将能够在那里进行如下配置:

   IntegrationFlows
    .from(Http.inboundReactiveGateway("/sse")
                        .requestMapping(m -> m.produces(MediaType.TEXT_EVENT_STREAM_VALUE)))

并且只完全依赖WebFlux,不依赖任何Servlet容器。

您使用什么Spring引导配置(
pom
)?您如何将Servlet容器和WebFlux混合使用?嗨,Artem,谢谢您的关注。我正在尝试使用
springbootplication v的所有默认值2.0.0.M2'
。我有一个带有上述两种方法的
@RestController
。基本上,它与您在ActiveMQ主题中的答案(配置方面)是一样的,这对我来说是有效的。但我接收到的不是JMS队列,而是来自http REST调用的消息。我刚刚用gradle依赖项更新了这个问题。谢谢好啊谢谢你的更新。我发现您同时具有
web
webflux
依赖项。它如何与
web
配合使用?我不能在本地检查,因为靴子现在有点坏了。谢谢你回来。好的,创建了一个新的quick项目,并删除了其中对
spring boot starter webflux
的依赖。但看起来没用。不过,没有发送任何事件。嗨,阿尔特姆,再次感谢您在这方面的努力和解释。您的代码可以工作,它有助于将其缩小到这样一个事实,即由于某种原因,在一个文件中定义的
@SpringBootApplication
@RestController
使其工作,但当它们位于不同的文件中时(这听起来更像是一个真实的案例),它就不能工作。看,问题在于您的
TestController
上缺少
@配置。没错,由于“轻配置”机制,httpReactiveSource()
@Bean
得到了正确的处理和注册。但是由于您直接从
eventMessages()
方法调用
httpReactiveSource()
方法,因此没有代理调用,
httpReactiveSource()
不会委托给bean工厂以获得正确的bean解析。因此,请考虑将<代码> HyrPrExcActudioService()/<代码>定义定义为<代码> @配置类,并使用<代码> @ AutoWordEng/<代码> <代码> TestCublue<代码> > <代码>发布者< /代码>,就是它,ARTEM!当通过
@配置定义时,它现在可以工作。我们终于找到了问题的根源!谢谢你们在这个框架上做得很棒!
curl -X POST http://localhost:8080/message/foo

curl -X POST http://localhost:8080/message/bar

curl -X POST http://localhost:8080/message/666
data:foo

data:bar

data:666
   IntegrationFlows
    .from(Http.inboundReactiveGateway("/sse")
                        .requestMapping(m -> m.produces(MediaType.TEXT_EVENT_STREAM_VALUE)))