如何使用 Jersey 拦截器获取请求体

新手上路,请多包涵

我在我的项目中使用 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 拦截器实现。

 public class JerseyFilter implements ContainerRequestFilter{

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

}

我想访问拦截器中的有效负载(请求主体)。由于数据为 JSON 格式,因此无法作为请求参数访问。 有没有办法在拦截器方法中获取请求体? 请指教。

原文由 Mono Jamoon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

这是您可以实现的一种方式,与 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());
    }
}

原文由 Arul Dhesiaseelan 发布,翻译遵循 CC BY-SA 3.0 许可协议

您只能读取一次内容,因为它是一个输入流。如果您在拦截器中获取它,那么您将无法在主解析中提供它。

您需要做的是创建一个过滤器来读取数据并将其提供给任何需要它的人。基本步骤是:

  • 在您的过滤器中创建一个新的 HttpServletRequestWrapper 子类,它将输入读入缓冲区并覆盖 getInputStream() 以向该缓冲区提供新的输入流
  • 将您的新子类传递到链中

原文由 user1596371 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题