簡體   English   中英

如何使用 Jersey 攔截器獲取請求正文

[英]How to use Jersey interceptors to get request body

我在我的項目中使用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();
}

漫畫豆:

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-interceptor 實現。

public class JerseyFilter implements ContainerRequestFilter{

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

} 

我想訪問攔截器中的有效負載(請求正文)。 由於數據為 JSON 格式,因此無法作為請求參數訪問。 有沒有辦法可以在攔截器方法中獲取請求正文? 請指教。

這是您可以實現的一種方式,與 Jersey 實現其日志過濾器的方式非常相似。 您可以讀取實體並將其粘貼到請求中,這樣您就不會意外地在過濾器中使用它。

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());
    }
}

您只能讀取一次內容,因為它是輸入流。 如果您在攔截器中獲取它,那么您將無法在主解析中提供它。

您需要做的是創建一個過濾器來讀取數據並將其提供給需要它的任何其他人。 基本步驟是:

  • 在您的過濾器中創建一個新的 HttpServletRequestWrapper 子類,它將輸入讀入緩沖區並覆蓋 getInputStream() 以向該緩沖區提供新的輸入流
  • 將您的新子類沿鏈傳遞

您可以從請求輸入流中獲取 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;
    }

不要使用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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM