如何从过滤器中查看消息?

发布于 2025-01-04 15:21:14 字数 772 浏览 1 评论 0原文

我尝试使用 javax.servlet.Filter 来查看消息。

public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
     BufferedReader reader = request.getReader();
     if ( reader.markSupported() ) {
         reader.mark( contentLen );
     }
     String content = reader.readLine();

     // search some pattern

     if ( reader.markSupported() ) {
         reader.reset();
     }
     chain.doFilter( request, response );
}

最终收到请求的 servlet 会抛出此异常:

java.lang.IllegalStateException: getReader() has already been called for this request

根据 javadoc,这是正确的行为。

我的问题是如何读取输入流的内容?

我还尝试了 ServletInputStream is = request.getInputStream();

I tried to use a javax.servlet.Filter to peek into a message.

public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
     BufferedReader reader = request.getReader();
     if ( reader.markSupported() ) {
         reader.mark( contentLen );
     }
     String content = reader.readLine();

     // search some pattern

     if ( reader.markSupported() ) {
         reader.reset();
     }
     chain.doFilter( request, response );
}

The servlet that finally receives the request throws this exeption:

java.lang.IllegalStateException: getReader() has already been called for this request

Which is correct behaviour according to the javadoc.

My questions is how can I read the content of the input-stream anyway?

I also tried ServletInputStream is = request.getInputStream();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

国际总奸 2025-01-11 15:21:14

未经测试,但您可能可以

  • 从请求输入流中读取所有字节并将它们写入字节数组,
  • 在此字节数组上构造一个缓冲读取器以读取过滤器中所需的内容,
  • 构造一个 HttpServletRequestWrapper 覆盖getInputStream() 通过字节数组返回流,
  • 将此包装器传递给过滤器链。

Not tested, but you could probably

  • read all the bytes from the request input stream and write them to a byte array,
  • construct a buffered reader over this byte array to read what you want in the filter,
  • construct a HttpServletRequestWrapper which overrides getInputStream() to return a stream over the byte array,
  • pass this wrapper to the filter chain.
夜访吸血鬼 2025-01-11 15:21:14

遵循 @JB Nizet 的方法得到了以下代码:

public class HttpServletRequestCopy extends HttpServletRequestWrapper {

    private final byte[]       buffer;

    private ServletInputStream sis;

    private BufferedReader     reader;

    public byte[] getBuffer() {
        return buffer;
    }

    public HttpServletRequestCopy( HttpServletRequest request) throws IOException {
        super( request );
        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        copyStream( request.getInputStream(), byteArrayOutputStream );
        buffer = byteArrayOutputStream.toByteArray();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        if ( reader == null ) {
            String characterEncoding = this.getCharacterEncoding();
            if ( characterEncoding == null ) {
                reader = new BufferedReader( new InputStreamReader( this.getInputStream() ) );
            }
            else {
                reader = new BufferedReader( new InputStreamReader( this.getInputStream(), characterEncoding ) );
            }
        }
        return reader;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if ( sis == null ) {
            final ByteArrayInputStream bais = new ByteArrayInputStream( buffer );
            sis = new ServletInputStream() {
                @Override
                public int read() throws IOException {
                    return bais.read();
                }
            };
        }
        return sis;
    }

    private void copyStream( InputStream input, OutputStream output) throws IOException {
        final byte[] bytes = new byte[ 1024 ];
        int length;
        while ( (length = input.read( bytes )) != -1 ) {
            output.write( bytes, 0, length );
        }
    }
}

Following the aproach from @JB Nizet led to this code:

public class HttpServletRequestCopy extends HttpServletRequestWrapper {

    private final byte[]       buffer;

    private ServletInputStream sis;

    private BufferedReader     reader;

    public byte[] getBuffer() {
        return buffer;
    }

    public HttpServletRequestCopy( HttpServletRequest request) throws IOException {
        super( request );
        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        copyStream( request.getInputStream(), byteArrayOutputStream );
        buffer = byteArrayOutputStream.toByteArray();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        if ( reader == null ) {
            String characterEncoding = this.getCharacterEncoding();
            if ( characterEncoding == null ) {
                reader = new BufferedReader( new InputStreamReader( this.getInputStream() ) );
            }
            else {
                reader = new BufferedReader( new InputStreamReader( this.getInputStream(), characterEncoding ) );
            }
        }
        return reader;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if ( sis == null ) {
            final ByteArrayInputStream bais = new ByteArrayInputStream( buffer );
            sis = new ServletInputStream() {
                @Override
                public int read() throws IOException {
                    return bais.read();
                }
            };
        }
        return sis;
    }

    private void copyStream( InputStream input, OutputStream output) throws IOException {
        final byte[] bytes = new byte[ 1024 ];
        int length;
        while ( (length = input.read( bytes )) != -1 ) {
            output.write( bytes, 0, length );
        }
    }
}
恋你朝朝暮暮 2025-01-11 15:21:14

ServletRequest.getInputStream()ServletRequest.getReader() 是非此即彼的,因此如果其中一个已经被调用,另一个就会失败。您可以使用简单的 try-catch 来解决此问题:

try {
    request.getInputStream();
} catch (IllegalStateException e) {
    // someone already called getReader(), so use it instead
    request.getReader();
}

注意!没有指定流或读取器应该可重置,因此如果您消耗了其中的任何字节,它们将不再可用到链中进一步的任何过滤器或 servlet。

ServletRequest.getInputStream() and ServletRequest.getReader() are either-or, so if either has already been called, the other one will fail. You can use a simple try-catch to navigate around this:

try {
    request.getInputStream();
} catch (IllegalStateException e) {
    // someone already called getReader(), so use it instead
    request.getReader();
}

NOTE! It is not specified that the stream or reader should be resettable, so if you consume any bytes off it, they will not be anymore available to any filters or servlets further in the chain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文