spring-webflux - 在 servlet 3.1 容器中使用 ServletHttpHandlerAdapter spring web-flux 进行请求转发
问题描述
根据servlet 3.1 容器上的文档,ServletHttpHandlerAdapter 可以注册为 servlet 并且可以支持 nio。我需要将请求转发到其他资源,如下所示
asyncContext.getRequest().getServletContext().getRequestDispatcher("/OtherResource")
.forward(asyncContext.getRequest(), asyncContext.getResponse());
在呼叫转发时,我遇到了错误。
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:624)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:211)
at com.nucleus.OtherServlet.doGet(OtherServlet.java:30)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:470)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
at com.nucleus.AsyncRequestProcessor.run(AsyncRequestProcessor.java:55)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
哪个是正确的,因为 spring 创建了 org.springframework.http.server.reactive.ServletServerHttpResponse 并最初调用 response.getOutputStream(),现在如何支持请求转发?
问题也记录到 spring jira 以供讨论 -链接
解决方案
Spring WebFlux 可以部署在 Servlet 3.1 容器上,这要归功于ServletHttpHandlerAdapter
- 但这并不意味着您可以在该应用程序中使用 Servlet 特定的 API。
首先,一旦您使用了异步 I/O Servlet 功能,就不能将它们与 Servlet API 上的阻塞 I/O 调用混合使用(请参阅有关 Servlet 3.1 异步 IO 的演示文稿)。
所以一般来说,你永远不应该尝试从 中获取特定于 Servlet 的对象ServerWebExchange
,而应该针对 Spring WebFlux 中的这个新的 HTTP 基础编写代码。
在 WebFlux 级别支持转发存在问题,但我不确定这最终会解决您的问题。我不了解您遇到的问题的具体细节,但 Spring WebFlux 已经支持使用阻塞 I/O 的模板引擎(请参阅此处的 Freemarker 支持)。
如果您尝试支持的模板引擎与 Servlet 相关联,那么您将无法获得适当的 WebFlux 支持,因为您可以在非 servlet 环境中运行 Spring WebFlux 应用程序。
推荐阅读
- nativescript - NativeScript tns 创建失败 - 在 POSTINSTALL 脚本
- vue.js - 让引导 vue 分页与 REST api 一起玩
- react-admin - 如何使用动态选项文本?
- ruby - 依赖注入导致 Rspec 失败和 IRB 失败
- python - 使用scrapy登录网站的问题
- c# - Unity Editor - C#:为什么我的列表重置为 null OnEnable?
- ruby-on-rails - 能够从网站上抓取一些文本,但不是所有的文本,使用 Watir
- javascript - 有没有办法使用 PHP/AJAX 来返回不仅仅是文本?
- django - Django:过滤时未显示在视图中的对象
- python - 如何在 python 3 版本中使用 super