HTTP サーブレット リクエストで 1 回の読み取り後に POST ボディ パラメータが失われるのはなぜですか?

Susan Sarandon
リリース: 2024-11-27 18:00:17
オリジナル
862 人が閲覧しました

Why Does My Http Servlet Request Lose POST Body Parameters After a Single Read?

HTTP サーブレット リクエストは、一度読み取った後に POST 本文からパラメータを失います

この状況では、POST リクエストを処理するときに次のことを理解することが重要です、パラメータは通常、リクエスト本文で送信されます。デフォルトでは、サーブレット コンテナはパラメータに初めてアクセスしたときに入力文字ストリームまたはバイナリ ストリームを消費します。その結果、フィルタ チェーン内のその後のアクセス試行は失敗します。

この問題を解決するには、考慮すべき主なアプローチが 2 つあります。

1.インターセプター コンポーネント:

フィルター チェーンを使用する代わりに、インターセプター コンポーネントを利用できます。これらのコンポーネントはアスペクトを使用して実装でき、消費されたリクエストの InputStream に依存せずに解析されたリクエスト本体の操作を可能にします。このアプローチは、独自のモデル オブジェクトを作成するためにリクエストの InputStream が 1 回だけ解析されるため、通常はより効率的です。

2. HttpServletRequestWrapper:

HTTP 層でフィルター チェーンが優先される場合、HttpServletRequestWrapper を拡張することが効果的な方法です。この手法には、リクエストの InputStream の消費とバイトのキャッシュが含まれます。

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
    private ByteArrayOutputStream cachedBytes;

    public MultiReadHttpServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (cachedBytes == null)
            cacheInputStream();

        return new CachedServletInputStream(cachedBytes.toByteArray());
    }

    @Override
    public BufferedReader getReader() throws IOException{
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    private void cacheInputStream() throws IOException {
        /* Cache the inputstream in order to read it multiple times. For
         * convenience, I use apache.commons IOUtils
         */
        cachedBytes = new ByteArrayOutputStream();
        IOUtils.copy(super.getInputStream(), cachedBytes);
    }

    /* An input stream which reads the cached request body */
    private static class CachedServletInputStream extends     ServletInputStream {

        private final ByteArrayInputStream buffer;

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

        @Override
        public int read() {
            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");
        }
    }
}
ログイン後にコピー

元のリクエストをフィルタ チェーンに渡す前に MultiReadHttpServletRequest でラップすることで、リクエストの本文を複数回読み取ることができます。このソリューションでは、getParameterXXX メソッドによる複数の読み取りも容易になることに注意してください。

編集:

ServletInputStream インターフェイスの新しいバージョンでは、isReady や setReadListener などの追加メソッドを使用する必要があります。実装されました。詳細については、この質問を参照してください。

以上がHTTP サーブレット リクエストで 1 回の読み取り後に POST ボディ パラメータが失われるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート