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

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

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

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

【问题讨论】:

    标签: java rest jersey


    【解决方案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
      }
      

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

      【讨论】:

        【解决方案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。
            猜你喜欢
            • 2013-01-11
            • 2021-08-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-02-24
            • 2014-11-15
            • 1970-01-01
            相关资源
            最近更新 更多