【问题标题】:Reactive Spring does not support HttpServletRequest as parameter in REST endpoint?Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?
【发布时间】: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 是要走的路...

标签: java spring spring-mvc spring-webflux


【解决方案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

【讨论】:

  • 该课程不再公开。过去是公开的吗?
猜你喜欢
  • 2019-04-23
  • 2020-12-21
  • 1970-01-01
  • 2019-05-06
  • 2019-08-15
  • 1970-01-01
  • 2013-03-19
  • 1970-01-01
相关资源
最近更新 更多