JavaサーブレットのPOSTリクエストからリクエストペイロードを取得する


113

JavaサーブレットにPOSTリクエストを送信しているJavaScriptライブラリがありますが、doPostメソッドではリクエストペイロードのコンテンツを取得できないようです。Chrome開発者ツールでは、すべてのコンテンツは[ヘッダー]タブの[リクエストペイロード]セクションにあり、コンテンツはそこにあります。POSTがdoPostメソッドによって受信されていることはわかっていますが、何も表示されません。

以下のためHttpServletRequest のオブジェクト、どのような方法私は、要求ペイロード内のデータを得ることができますか?

実行するrequest.getParameter()request.getAttributes() 、両方ともデータなしになる


たとえば、本文にキーワードがある場合は、次のように指定する必要があります。Stringkeyword = request.getParameter( "keyword");
justMe 2013年

リクエストを送信するJavaScriptコードを見るのは興味深いでしょう。リクエストパラメータを誤った方法で構成しているようです。
BalusC 2013年

@Razhええ、そうですね、私が試した方法を指定しただけです。BalusC私はresumable.jsライブラリを使用して分割ファイルのアップロードを処理しています
Fasih Awan 2013

4
私が誤解していない場合は、入力ストリームから読み取る前にrequest.getParameter()を使用しないことが重要です。そうしないと、データは利用できません(すでに読み取られます)。
Jeach 2013

回答:


110

簡単な答え:
getReader()を使用してリクエストの本文を読み取ります

詳細:
本文のデータを読み取る方法は2つあります。

  1. getReader()リクエストの本文を読み取ることができるBufferedReaderを返します。

  2. getInputStream()バイナリデータを読み取る必要がある場合は、ServletInputStreamを返します。

ドキュメントからの注記:「両方ではなく、本文を読み取るために[いずれかのメソッド]を呼び出すことができます。」


4
問題ありません。それは少し隠されています
davidfrancis

25
この投稿は、フィルターでこれを使用したばかりで、他に本文を読み取ることができないものを発見した場合に役立ちます。 natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa 14

これは本当に悪い答えです。
SgtPooki

1
@SgtPookiは、コメントに何らかの理由を追加してください。
davidfrancis

@davidfrancis私はここであなたを個人的に判断しようとはしていませんが、コンテキストを提供していません。ドキュメントへのリンクも例もありません。私のコメントへのあなたの返信は、答え自体よりも多くの努力を必要としたようです。
SgtPooki

68
String payloadRequest = getBody(request);

この方法を使用する

public static String getBody(HttpServletRequest request) throws IOException {

    String body = null;
    StringBuilder stringBuilder = new StringBuilder();
    BufferedReader bufferedReader = null;

    try {
        InputStream inputStream = request.getInputStream();
        if (inputStream != null) {
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            char[] charBuffer = new char[128];
            int bytesRead = -1;
            while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                stringBuilder.append(charBuffer, 0, bytesRead);
            }
        } else {
            stringBuilder.append("");
        }
    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }

    body = stringBuilder.toString();
    return body;
}

6
request.getInputStream()リクエストの文字エンコーディングを尊重しないことを考慮してくださいrequest.getReader()。したがって、この例ではデフォルトのシステム文字セットを使用しています。
Vadzim 14

9
new BufferedReader(new InputStreamReader(request.getInputStream()))単純にrequest.getReader()バッファリングされ、リクエストのエンコーディングも保持されるように簡略化できます。
Vadzim 14

1
例外がスローされたため、このソリューションは役に立ちましたjavax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this request。リーダーが既に開いているためにgetReader()を呼び出したときです。
Benjamin Slabbert 2017

52

リクエストからバッファリーダーを使用して読み取ることができます

    // Read from request
    StringBuilder buffer = new StringBuilder();
    BufferedReader reader = request.getReader();
    String line;
    while ((line = reader.readLine()) != null) {
        buffer.append(line);
    }
    String data = buffer.toString()

40

Java 8ストリーム

String body = request.getReader().lines()
    .reduce("", (accumulator, actual) -> accumulator + actual);

これは興味深いですが、文字列の連結という点ではかなり非効率に見えます。これを改善できる方法はありますか?
davidfrancis

11
String body = request.getReader()。lines()。collect(Collectors.joining()); うまくいくかもしれません。Collectors.joiningは、内部ではStringBuilderを使用しているようです。
Oliver Kohll 2016

3
改行を保存するには、request.getReader()。lines()。collect(joining( "\ n"))を使用する必要があると思います。
MichaelBöckling2017

Java 8では、ストリームは並列処理されるため、シーケンシャルメソッドを追加する必要があります。そうしないと、データの誤った部分がマージされます-String body = request.getReader()。lines()。sequential()。reduce(System.lineSeparator()、( accumulator、actual)-> accumulator + actual)
Jatin Bodarya

2
あなたは置き換えることができ(accumulator, actual) -> accumulator + actualString::concat
shmosel



5

ペイロードをJSONで送信できる場合、これはプレイロードを読み取る最も便利な方法です。

データクラスの例:

public class Person {
    String firstName;
    String lastName;
    // Getters and setters ...
}

ペイロードの例(リクエスト本文):

{ "firstName" : "John", "lastName" : "Doe" }

サーブレットのペイロードを読み取るコード(com.google.gson。*が必要):

Person person = new Gson().fromJson(request.getReader(), Person.class);

それで全部です。いい、簡単、きれい。content-typeヘッダーをapplication / jsonに設定することを忘れないでください。


2

リソースを使ってJava 8を試す:

    StringBuilder stringBuilder = new StringBuilder();
    try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
        char[] charBuffer = new char[1024];
        int bytesRead;
        while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
            stringBuilder.append(charBuffer, 0, bytesRead);
        }
    }

1

あなただけが必要です

request.getParameterMap()

POSTおよびGETを取得するためのパラメーター。

メソッドはを返しますMap<String,String[]>

あなたはマップのパラメータを読むことができます

Map<String, String[]> map = request.getParameterMap();
//Reading the Map
//Works for GET && POST Method
for(String paramName:map.keySet()) {
    String[] paramValues = map.get(paramName);

    //Get Values of Param Name
    for(String valueOfParam:paramValues) {
        //Output the Values
        System.out.println("Value of Param with Name "+paramName+": "+valueOfParam);
    }
}

2
注意:パラメータは、エンコーディングを使用する場合にのみ使用できますapplication/x-www-form-urlencoded。の場合multipart/form-data、明らかにボディパーツにアクセスしrequest.getReader()て手動で解析する必要があります。
Twonkeys 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.