Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?
Posted
技术标签:
【中文标题】Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?【英文标题】:Reactive Spring does not support HttpServletRequest as parameter in REST endpoint? 【发布时间】:2017-03-14 15:57:08 【问题描述】:我创建了一个如下所示的 RestController:
@RestController
public class GreetingController
@RequestMapping(value = "/greetings", method = RequestMethod.GET)
public Mono<Greeting> greeting(HttpServletRequest request)
return Mono.just(new Greeting("Hello..." + request.toString()));
不幸的是,当我尝试点击“问候”端点时,我得到了一个异常:
java.lang.IllegalStateException:没有类型的参数 [0] 的解析器 [org.apache.catalina.servlet4preview.http.HttpServletRequest]
我正在使用
compile('org.springframework.boot.experimental:spring-boot-starter-web-reactive')
如何解决这个问题?
Link 到完整的堆栈跟踪。 Link build.gradle
---------编辑---------
使用界面。现在得到:
java.lang.IllegalStateException:没有类型的参数 [0] 的解析器 [javax.servlet.http.HttpServletRequest] on 方法(其余相同)
【问题讨论】:
您使用了错误的HttpServletRequest
。使用接口而不是具体的实现。
已修复,但 Spring 仍然给您带来麻烦。
尝试在 HttpServletRequest 请求之前添加@Context? cxf.apache.org/docs/…
Nope 没有一个“HandlerMethodArgumentResolver”,如下面我的回答中提到的那样处理这个注释。我认为 ServletServerHttpRequest 是要走的路...
【参考方案1】:
您应该从不在 Spring Reactive Web 应用程序中使用 Servlet API。这不受支持,这会使您的应用程序依赖于容器,而 Spring Web Reactive 可以与 Netty 等非 Servlet 运行时一起使用。
您应该使用 Spring 提供的 HTTP API;这是您的代码示例,有一些更改:
import org.springframework.http.server.reactive.ServletServerHttpRequest;
@RestController
public class GreetingController
@GetMapping("/greetings")
public Mono<Greeting> greeting(ServerHttpRequest request)
return Mono.just(new Greeting("Hello..." + request.getURI().toString()));
您可以注入ServerWebExchange
或直接注入ServerHttpRequest
/ ServerHttpResponse
。
【讨论】:
我可以理解“使您的应用程序依赖于容器”,但是“不支持”是什么意思? 您用来获取 servlet 响应的类是内部的,不应在应用程序代码中使用。这也可能会带来很大的问题,因为您应该只使用 Servlet 3.1 异步 IO API 来写入主体,否则您将面临完全阻塞您的应用程序的风险。【参考方案2】:深入调用层次结构,发现有这个类 InvocableHandlerMethod,在 org.springframework.web.reactive.result.method 包中 ,其中有:
private List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
这个类中有一个resolveArguments()方法,被调用来“解析参数”。不幸的是,没有解析器 javax.servlet.http.HttpServletRequest 在此列表中。
但是有一个 ServerWebExchangeArgumentResolver 能够解析 ServletServerHttpRequest,我可以从中提取 HttpServletRequest。是啊……
所以端点看起来像:
@RequestMapping(value = "/greetings", method = RequestMethod.GET)
public Mono<Greeting> greeting(ServletServerHttpRequest servletServerHttpRequest)
HttpServletRequest httpServletRequest = servletServerHttpRequest.getServletRequest();
.
.
.
重要的是 ServletServerHttpRequest 来自包 org.springframework.http.server.reactive
【讨论】:
该课程不再公开。过去是公开的吗?以上是关于Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?的主要内容,如果未能解决你的问题,请参考以下文章
Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?
Spring WebFlux Reactive 和 Kotlin Coroutines 启动错误