18

私はREST-Jersey自分のプロジェクトで使用しています。すべてのPOSTデータはJSON形式で送信され、サーバー側でそれぞれのBeanにマーシャリングされません。このようなもの:

サーバーへのリクエストの送信:

    $('a#sayHelloPost').click(function(event){
        event.preventDefault();
        var mangaData = {
            title:'Bleach',
            author:'Kubo Tite'
        }
        var formData=JSON.stringify(mangaData);
        console.log(formData);
        $.ajax({
                url:'rest/cred/sayposthello',
                type: 'POST',
                data: formData,
                dataType: 'json',
                contentType:'application/json'
        })
});

ペイロード:

{"title":"Bleach","author":"Kubo Tite"}

サーバー側:

@POST
@Path("/sayposthello")
@Produces(MediaType.APPLICATION_JSON)
public Response sayPostHello(MangaBean mb){
    System.out.println(mb);
    return Response.status(200).build();
}

MangaBean:

public class MangaBean {
    private String title;
    private String author;
    @Override
    public String toString() {
        return "MangaBean [title=" + title + ", author=" + author + "]";
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
}

コンソールでの出力:

MangaBean [title=Bleach, author=Kubo Tite]

ここからRESTインターセプターの実装を取得しました。

public class JerseyFilter implements ContainerRequestFilter{

    @Override
    public ContainerRequest filter(ContainerRequest req) {
        return req;
    }

} 

インターセプターのペイロード(リクエストボディ)にアクセスしたい。データはJSON形式であるため、リクエストパラメータとしてアクセスすることはできません。インターセプターメソッドでリクエスト本文を取得する方法はありますか?ご意見をお聞かせください。

4

4 に答える 4

30

これは、Jerseyがロギングフィルターを実装する方法と非常によく似た、実装できる1つの方法です。エンティティを読み取ってリクエストに貼り付けることができるため、誤ってフィルタでエンティティを消費することはありません。

import com.sun.jersey.api.container.ContainerException;
import com.sun.jersey.core.util.ReaderWriter;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class JerseyFilter implements ContainerRequestFilter {

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        InputStream in = request.getEntityInputStream();
        final StringBuilder b = new StringBuilder();
        try {
            if (in.available() > 0) {
                ReaderWriter.writeTo(in, out);

                byte[] requestEntity = out.toByteArray();
                printEntity(b, requestEntity);

                request.setEntityInputStream(new ByteArrayInputStream(requestEntity));
            }
            return request;
        } catch (IOException ex) {
            throw new ContainerException(ex);
        }

    }

    private void printEntity(StringBuilder b, byte[] entity) throws IOException {
        if (entity.length == 0)
            return;
        b.append(new String(entity)).append("\n");
        System.out.println("#### Intercepted Entity ####");
        System.out.println(b.toString());
    }
}
于 2013-01-29T09:15:04.980 に答える
5

コンテンツは入力ストリームであるため、コンテンツを読み取ることができるのは1回だけです。インターセプターでそれを取得すると、メインの構文解析でそれを提供できなくなります。

あなたがする必要があるのは、データを読み取り、それを必要とする他の誰もがそれを利用できるようにするフィルターを作成することです。基本的な手順は次のとおりです。

  • フィルタで、HttpServletRequestWrapperの新しいサブクラスを作成します。このサブクラスは、入力をバッファに読み込み、getInputStream()をオーバーライドして、そのバッファに新しい入力ストリームを提供します。
  • 新しいサブクラスをチェーンに渡します
于 2013-01-28T13:18:20.313 に答える
4

POST本文はリクエスト入力ストリームから取得できます。次のようなものを試してください。

        @Override
        public ContainerRequest filter(ContainerRequest req) {
            try{

            StringWriter writer = new StringWriter();       
                IOUtils.copy(req.getEntityInputStream(), writer, "UTF-8");

            //This is your POST Body as String      
            String body = writer.toString();

                }
            catch (IOException e) {}
         return req; }
于 2013-01-28T11:44:59.123 に答える
4

in.available()Inputstreamの合計バイトをチェックするためにメソッドを使用しないでください。一部のクライアントはこの値を設定しません。この場合、メッセージ本文の入力ストリームが存在していても、ファウルになります。

 InputStream in = request.getEntityInputStream();
        final StringBuilder b = new StringBuilder();
        try {
            if (in.available() > 0)

以下のコードを使用してください

String json = IOUtils.toString(requestContext.getEntityStream(), Charsets.UTF_8);
            messageBody = json;
            InputStream in = IOUtils.toInputStream(json);
            requestContext.setEntityStream(in);
于 2017-01-16T11:56:49.083 に答える