HttpServletRequestWrapper,setReadListener / isFinished / isReady 的示例实现?

40

我正在尝试适应一个HttpServletRequestWrapper(请参见如何多次读取request.getInputStream()),以便在过滤器中使用后能够读取HTTP Post body。现在,我遇到了如何实现ServletInputStream的挑战。根据规范3.1,必须实现新方法。

  • isFinished()
  • isReady()
  • setReadListener()

我正在寻找这些方法可以如何实现的示例或一些代码。有什么提示吗?


2
这些方法是Servlet 3.1,而不是Servlet 3.0。 - Brian Clozel
@BrianClozel 感谢您指出,我已更新问题。 - Marco
你实现了这个吗? - yathirigan
请参考 http://mpas.github.io/post/2015/06/httpservletwrapper-3.1/ 了解我们如何实现此功能。 - Marco
2个回答

38

示例实现:

import com.google.common.primitives.Bytes;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class AuthenticationRequestWrapper extends HttpServletRequestWrapper {

    // tag::variables[]
    private byte[] requestBody = new byte[0];
    private boolean bufferFilled = false;
    // end::variables[]

    /**
     - Constructs a request object wrapping the given request.
     *
     - @param request The request to wrap
     - @throws IllegalArgumentException if the request is null
     */
    public AuthenticationRequestWrapper(HttpServletRequest request) {
        super(request);
    }


    // tag::getRequestBody[]
    public byte[] getRequestBody() throws IOException {
        if (bufferFilled) {
            return Arrays.copyOf(requestBody, requestBody.length);
        }

        InputStream inputStream = super.getInputStream();

        byte[] buffer = new byte[102400]; // 100kb buffer

        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            requestBody = Bytes.concat(this.requestBody, Arrays.copyOfRange(buffer, 0, bytesRead)); // <1>
        }

        bufferFilled = true;

        return requestBody;
    }
    // end::getRequestBody[]

    // tag::getInputStream[]
    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new CustomServletInputStream(getRequestBody()); // <1>
    }
    // end::getInputStream[]

    private static class CustomServletInputStream extends ServletInputStream {

        private ByteArrayInputStream buffer;

        public CustomServletInputStream(byte[] contents) {
            this.buffer = new ByteArrayInputStream(contents);
        }

        @Override
        public int read() throws IOException {
            return buffer.read();
        }

        @Override
        public boolean isFinished() {
            return buffer.available() == 0;
        }

        @Override
        public boolean isReady() {
            return true;
        }

        @Override
        public void setReadListener(ReadListener listener) {
            throw new RuntimeException("Not implemented");
        }
    }
}

4
出现错误:"getReader() 已经为此请求调用"。 - Bikesh M

3

您可以在Spring框架中查看MockHttpServletRequest

源代码可以在这里找到。

由于Spring是采用Apache2许可证的开源软件,因此您可以从代码开始构建自己的版本。


1
我找不到所需信息的位置。 - Marco
你实现了这个吗? - yathirigan
我总是使用MockHttpServletRequest进行测试。 - Giovanni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接