我已经使用/ sse webflux资源设置了一个示例应用程序,该资源生成了text / event-stream。
当我尝试使用curl调用资源时,当我请求没有Accept标头时我得到404,当我使用Accept标头请求时得到406,如下所示:
curl -v http://localhost:8080/events
curl -H "Accept: text/event-stream" -v http://localhost:8080/events
到目前为止,我无法使其发挥作用。
我对Webflux.inboundGateway
使用以下示例代码(与其他Http.inboundGateway
流一起工作正常):
@SpringBootApplication
@EnableIntegration
@EnableWebFlux
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public IntegrationFlow sseFlow() {
return IntegrationFlows
.from(WebFlux.inboundGateway("/sse")
.requestMapping(m -> m.produces(MediaType.TEXT_EVENT_STREAM_VALUE)))
.handle((p, h) -> Flux.just("foo", "bar", "baz"))
.get();
}
// ... more integration flows, but with Http.inboundGateway
在我的pom.xml中,我有这些与webflux相关的依赖项:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
在启动时,我收到WebfluxIntegrationRequestMappingHandlerMapping
已映射/ sse的消息(它只显示xIntegrationRequestMappingHandlerMapping
,因为类名太长了,幸运的是我们看到了x
):
2018-05-05 08:08:27.269 INFO 45160 --- [ restartedMain] xIntegrationRequestMappingHandlerMapping : Mapped "{[/sse],methods=[GET || POST],produces=[text/event-stream]}" onto public abstract reactor.core.publisher.Mono<java.lang.Void> org.springframework.web.server.WebHandler.handle(org.springframework.web.server.ServerWebExchange)
现在有趣的部分。在以下调试日志中,您可以看到应用程序显然不考虑 WebfluxIntegrationRequestMappingHandlerMapping
,而只考虑其他HandlerMappings。因此,它选择ResourceHttpRequestHandler。
在没有Accept标头的情况下调用时会发生这种情况:
2018-05-04 15:59:12.281 DEBUG 36196 --- [nio-8080-exec-3] o.s.b.w.s.f.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@6b1c36b4
2018-05-04 15:59:12.281 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/sse]
2018-05-04 15:59:12.281 DEBUG 36196 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /sse
2018-05-04 15:59:12.281 DEBUG 36196 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/sse]
2018-05-04 15:59:12.281 DEBUG 36196 --- [nio-8080-exec-3] .IntegrationRequestMappingHandlerMapping : Looking up handler method for path /sse
2018-05-04 15:59:12.282 DEBUG 36196 --- [nio-8080-exec-3] .IntegrationRequestMappingHandlerMapping : Did not find handler method for [/sse]
2018-05-04 15:59:12.282 DEBUG 36196 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/sse] are [/**]
2018-05-04 15:59:12.282 DEBUG 36196 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/sse] are {}
2018-05-04 15:59:12.282 DEBUG 36196 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/sse] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@2b3f154f]]] and 1 interceptor
2018-05-04 15:59:12.282 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/sse] is: -1
2018-05-04 15:59:12.282 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2018-05-04 15:59:12.283 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Successfully completed request
2018-05-04 15:59:12.283 DEBUG 36196 --- [nio-8080-exec-3] o.s.b.w.s.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@6b1c36b4
2018-05-04 15:59:12.283 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/error]
2018-05-04 15:59:12.283 DEBUG 36196 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
2018-05-04 15:59:12.283 DEBUG 36196 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)]
2018-05-04 15:59:12.284 DEBUG 36196 --- [nio-8080-exec-3] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'basicErrorController'
2018-05-04 15:59:12.284 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/error] is: -1
2018-05-04 15:59:12.286 DEBUG 36196 --- [nio-8080-exec-3] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Written [{timestamp=Fri May 04 15:59:12 CEST 2018, status=404, error=Not Found, message=No message available, path=/sse}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7d49dc3e]
2018-05-04 15:59:12.286 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2018-05-04 15:59:12.286 DEBUG 36196 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Successfully completed request
当使用 Accept头调用时,我会在处理/ error资源时在日志中看到另一个警告Resolved exception caused by Handler execution: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
:
2018-05-05 07:47:19.356 DEBUG 36196 --- [nio-8080-exec-1] o.s.b.w.s.f.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@6b1c36b4
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/sse]
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /sse
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/sse]
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] .IntegrationRequestMappingHandlerMapping : Looking up handler method for path /sse
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] .IntegrationRequestMappingHandlerMapping : Did not find handler method for [/sse]
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/sse] are [/**]
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/sse] are {}
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/sse] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@2b3f154f]]] and 1 interceptor
2018-05-05 07:47:19.357 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/sse] is: -1
2018-05-05 07:47:19.358 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2018-05-05 07:47:19.358 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Successfully completed request
2018-05-05 07:47:19.358 DEBUG 36196 --- [nio-8080-exec-1] o.s.b.w.s.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@6b1c36b4
2018-05-05 07:47:19.359 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/error]
2018-05-05 07:47:19.359 DEBUG 36196 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
2018-05-05 07:47:19.359 DEBUG 36196 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)]
2018-05-05 07:47:19.359 DEBUG 36196 --- [nio-8080-exec-1] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'basicErrorController'
2018-05-05 07:47:19.359 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/error] is: -1
2018-05-05 07:47:19.360 DEBUG 36196 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
2018-05-05 07:47:19.360 DEBUG 36196 --- [nio-8080-exec-1] .w.s.m.a.ResponseStatusExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
2018-05-05 07:47:19.360 DEBUG 36196 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolving exception from handler [public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
2018-05-05 07:47:19.360 WARN 36196 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
2018-05-05 07:47:19.360 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2018-05-05 07:47:19.360 DEBUG 36196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Successfully completed request
为什么Spring不考虑WebfluxIntegrationRequestMappingHandlerMapping
?或者这里出了什么问题?
答案 0 :(得分:1)
您必须决定是运行反应式应用程序还是运行mvc应用程序。当spring-boot-starter-web和spring-boot-starter-webflux都被定义为类路径的依赖项时,Spring Boot默认配置Spring MVC应用程序。那是我的问题。
我不得不删除spring-boot-starter-web和spring-integration-http,以便Spring Boot启动Netty,而不是Tomcat。另一种方法是明确地告诉Spring:
public static void main(String[] args) {
SpringApplication application = new SpringApplication(WebfluxApplication.class);
application.setWebApplicationType(WebApplicationType.REACTIVE);
application.run(WebfluxApplication.class, args);
}
在一个应用程序中混合spring-integration-http和spring-integration-webflux Webflux.inboundGateway似乎是不可能的,你必须创建两个独立的应用程序,一个启动Tomcat用于servlet请求,另一个启动Netty。
如果您不想切换到被动应用程序,可能的解决方法: How to create a Spring Reactor Flux from Http integration flow?显示如何将传入的http POSTS路由到被动发布者,并使用SSE通过@GetMapping MVC资源将其作为事件提供。
另见https://github.com/spring-projects/spring-boot/issues/11025。