如何使用 Jersey 获取完整的 REST 请求正文?

Posted

技术标签:

【中文标题】如何使用 Jersey 获取完整的 REST 请求正文?【英文标题】:How to get full REST request body using Jersey? 【发布时间】:2010-12-16 01:38:34 【问题描述】:

如何使用 Jersey 获取 POST 请求的完整 HTTP REST 请求正文?

在我们的例子中,数据是 XML。大小从 1K 到 1MB 不等。

docs 似乎表明您应该使用MessageBodyReader,但我看不到任何示例。

【问题讨论】:

【参考方案1】:

用这个单一的代码试试这个:

import javax.ws.rs.POST;
import javax.ws.rs.Path;

@Path("/serviceX")
public class MyClassRESTService 

    @POST
    @Path("/doSomething")   
    public void someMethod(String x) 

        System.out.println(x);
                // String x contains the body, you can process
                // it, parse it using JAXB and so on ...

    

try rest 服务的 url 结束 .... /serviceX/doSomething

【讨论】:

【参考方案2】:

看来您必须在此处使用MessageBodyReader。这是一个使用 jdom 的示例:

import org.jdom.Document;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.MediaType;
import javax.ws.rs.ext.MultivaluedMap;
import java.lang.reflect.Type;
import java.lang.annotation.Annotation;
import java.io.InputStream;

@Provider // this annotation is necessary!
@ConsumeMime("application/xml") // this is a hint to the system to only consume xml mime types
public class XMLMessageBodyReader implements MessageBodyReader<Document> 
  private SAXBuilder builder = new SAXBuilder();

  public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) 
    // check if we're requesting a jdom Document
    return Document.class.isAssignableFrom(type);
  

  public Document readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
    try 
      return builder.build(entityStream);
    
    catch (Exception e) 
      // handle error somehow
    
   

将此类添加到您的球衣部署将处理的资源列表中(我认为通常通过 web.xml 配置)。然后,您可以在您的常规资源类之一中使用此阅读器,如下所示:

@Path("/somepath") @POST
public void handleXMLData(Document doc) 
  // do something with the document

我还没有验证这是否与键入的内容完全一致,但这就是它的要点。更多阅读:

http://weblogs.java.net/blog/mhadley/archive/2008/02/integrating_jer_2.html http://blogs.oracle.com/sandoz/entry/jersey_and_abdera_with_a

【讨论】:

【参考方案3】:

由于您是在 xml 中传输数据,因此您也可以直接从/到 pojos(取消)编组。

jersey user guide 中有一个示例(以及更多信息),我在这里复制:

带有 JAXB 注释的 POJO:

@XmlRootElement
public class Planet 
    public int id;
    public String name;
    public double radius;

资源:

@Path("planet")
public class Resource 

    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Planet getPlanet() 
        Planet p = new Planet();
        p.id = 1;
        p.name = "Earth";
        p.radius = 1.0;

        return p;
    

    @POST
    @Consumes(MediaType.APPLICATION_XML)
    public void setPlanet(Planet p) 
        System.out.println("setPlanet " + p.name);
    

      

生成/使用的 xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<planet>
    <id>1</id>
    <name>Earth</name>
    <radius>1.0</radius>
</planet>

【讨论】:

【参考方案4】:

您可以使用@Consumes 注释来获取完整的正文:

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;

@Path("doc")
public class BodyResource

  @POST
  @Consumes(MediaType.APPLICATION_XML)
  public void post(Document doc) throws TransformerConfigurationException, TransformerException
  
    Transformer tf = TransformerFactory.newInstance().newTransformer();
    tf.transform(new DOMSource(doc), new StreamResult(System.out));
  

注意:不要忘记请求中的“Content-Type: application/xml”标头。

【讨论】:

【参考方案5】:

事实证明,您根本不需要做太多事情。

见下文 - 参数 x 将包含完整的 HTTP 正文(在我们的例子中是 XML)。

@POST
public Response go(String x) throws IOException 
    ...

【讨论】:

我还需要添加一个@Consumes(MediaType.TEXT_PLAIN)。 或者我猜@Consumes 一般是什么? 这对于在泽西岛调试消息非常有帮助,无论出于何种原因,网络检查都不是一种选择,但代码更改是(在我的情况下是本地集成测试)。 我收到以下错误:无法将类型“java.lang.String”编组为元素,因为它缺少 XmlRootElement 注释。 @sdorra 的回答帮助了我:只使用 org.w3c.dom.Document 作为类型,而不是 java.lang.String。

以上是关于如何使用 Jersey 获取完整的 REST 请求正文?的主要内容,如果未能解决你的问题,请参考以下文章

Jersey REST 客户端请求 - 如何设置源 IP 地址

Jersey REST API 请求不起作用

jersey rest web 服务与 Activemq 中间件集成

Jersey REST API 安全性

POST 到 Jersey REST 服务收到错误 415 Unsupported Media Type

如何在 jersey 1.11 过滤器中添加自定义响应和中止请求