Java 如何从Http集成流创建Spring反应堆流量?
我有一个和这个问题很相似的问题 一个区别是消息来自Http端点而不是JMS队列。问题是消息通道由于某种原因没有被填充,或者它没有被Flux.from()拾取。日志条目显示,GenericMessage是从Http集成流创建的,有效负载作为路径变量,但不会进入队列/发布到通道?我尝试了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
.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)))