gpt4 book ai didi

spring-boot - 为什么我的请求实体 InputStream 在 ContainerRequestFilter (Spring+Jersey) 中总是为空

转载 作者:行者123 更新时间:2023-12-04 03:09:56 29 4
gpt4 key购买 nike

我完全无法在 JaxRS ContainerRequestFilter 中获取请求负载/表单。

我的设置:

  • JDK 8
  • SpringBoot 1.3.0.RELEASE
  • Jersey 2.22.1(来自 SpringBoot)

  • 这是我的 pom :(来自 Spring Initialzr)
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.0.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
    </properties>

    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jersey</artifactId>
    </dependency>

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    </dependencies>

    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>

    </project>

    这是我的应用程序类:
    @SpringBootApplication
    public class DemoApplication {

    public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
    }
    }

    这是我的 JerseyConfig:
    @Configuration
    public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
    register(HelloController.class);
    register(MyFilter.class);
    }
    }

    这是我的 HelloController:
    @Component
    @Path("/hello")
    public class HelloController {

    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @POST
    public String onHelloRequest(@FormParam("foo") String foo) {
    System.out.println(foo);
    return foo + "bar";
    }
    }

    这是我遇到的问题的核心部分,ContainerRequestFilter:
    public class MyFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext ctx) throws IOException {

    System.err.println("I'm in the filter");

    // Solution #1 doesn't work
    if (ctx instanceof ContainerRequest) {
    ContainerRequest request = (ContainerRequest) ctx;

    request.bufferEntity();
    Form f = request.readEntity(Form.class);
    System.err.println(f.asMap().toString());
    }

    // Solution #2 doesn't work either
    InputStream inputStream = ctx.getEntityStream();
    StringBuilder textBuilder = new StringBuilder();
    try (Reader reader = new BufferedReader(new InputStreamReader
    (inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) {
    int c = 0;
    while ((c = reader.read()) != -1) {
    textBuilder.append((char) c);
    }
    }
    System.err.println(textBuilder.toString());
    }
    }

    如您所见,这是一个使用 Jersey 的非常精简的 SpringBoot 示例。但是,看起来 ContainerRequestFilter 中的 InputStream 已被使用。我用 Javax ServletFilter 试过了,我也遇到了同样的问题。

    Spring-web 是否有可能在调用 Jersey 之前使用 InputStream?

    请帮我。

    编辑

    为了测试它,我使用了 POSTMAN 并发送了:

    发布 http://localhost:8080/hello

    header :

    内容类型 = 应用程序/x-www-form-urlencoded

    有效载荷:

    富=酒吧

    我的回复是

    野蛮人

    我的控制台输出是

    我在过滤器中

    {}//解决方案 #1 <- 应该类似于 foo=bar

    //解决方案 #2 <- 一个空字符串

    酒吧

    编辑2

    我在控制台中也有该消息,即使没有任何自定义 Filter :

    2015-11-21 20:14:05.438 WARN 4440 --- [nio-8080-exec-2] o.glassfish.jersey.servlet.WebComponent:对 URI http://localhost:8080/hello 的 servlet 请求在请求正文中包含表单参数,但请求正文已被 servlet 或访问请求参数的 servlet 过滤器使用。只有使用 @FormParam 的资源方法才能按预期工作。通过其他方式消耗请求正文的资源方法将无法按预期工作。

    在将 InputStream 传递给 Jersey 之前,它肯定看起来像其他东西消耗了 InputStream,使每个 Jax-RS Filters|Interceptors 都没有状态。

    最佳答案

    这里是“解决方案”

    在 SpringBoot 中,如果添加 starter-web 模块,它将添加 spring:webmvc,这似乎与 JaxRS 和 Servlet 过滤器不兼容。如果您使用 SpringBoot 和 Jersey,请确保 webmvc jar 不在类路径中。

    Spring 堆栈将消耗 Servlet 的 Request InputStream 并且管道中的每个向下拦截器/过滤器都将一无所有。

    这是在 Servlet 过滤器中获取请求有效负载的工作代码片段

    public MyFilter implements Filter
    {


    @Override
    public final void doFilter(
    final ServletRequest request,
    final ServletResponse response,
    final FilterChain chain)
    throws IOException,
    ServletException {


    getRawFormPayload((HttpServletRequest) request);
    chain.doFilter(request, response);
    }

    protected String getRawFormPayload(HttpServletRequest request) {

    final int contentLength = request.getContentLength();
    final StringBuilder payloadBuilder = new StringBuilder(contentLength);
    try {
    final InputStream inputStream = request.getInputStream();
    final BufferedReader reader =
    new BufferedReader(new InputStreamReader(inputStream, request.getCharacterEncoding()));

    // Buffer should not be higher than the content-length of the request
    reader.mark(contentLength + 1);
    final char[] charBuffer = new char[contentLength + 1];
    int bytesRead = -1;

    while ((bytesRead = reader.read(charBuffer)) > 0) {
    payloadBuilder.append(charBuffer, 0, bytesRead);
    }

    // Reset the buffer so the next Filter/Interceptor have unaltered InputStream
    reader.reset();

    } catch (final IOException e) {
    this.LOG.error(e.getMessage(), e);
    }
    return payloadBuilder.toString();
    }
    }

    关于spring-boot - 为什么我的请求实体 InputStream 在 ContainerRequestFilter (Spring+Jersey) 中总是为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33846197/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com