How can one get the full HTTP REST request body for a POST
request using Jersey?
如何使用Jersey获得一个POST请求的完整HTTP REST请求主体?
In our case the data will be XML. Size would vary from 1K to 1MB.
在我们的例子中,数据将是XML。大小从1K到1MB不等。
The docs seem to indicate you should use MessageBodyReader
but I can't see any examples.
文档似乎表明您应该使用MessageBodyReader,但我看不到任何示例。
5 个解决方案
#1
75
Turns out you don't have to do much at all.
原来你根本不需要做什么。
See below - the parameter x
will contain the full HTTP body (which is XML in our case).
参见下面——参数x将包含完整的HTTP主体(在我们的例子中是XML)。
@POST
public Response go(String x) throws IOException {
...
}
#2
14
You could use the @Consumes annotation to get the full body:
您可以使用@消费注释来获得完整的主体:
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));
}
}
Note: Don't forget the "Content-Type: application/xml" header by the request.
注意:不要忘记请求的“内容类型:应用程序/xml”头。
#3
11
Try this using this single code:
尝试使用这段代码:
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 ...
}
}
The url for try rest services ends .... /serviceX/doSomething
试着rest服务的url ....结束/ serviceX doSomething
#4
6
Since you're transferring data in xml, you could also (un)marshal directly from/to pojos.
由于您正在用xml传输数据,您还可以(un)从/到pojo进行封送。
There's an example (and more info) in the jersey user guide, which I copy here:
泽西用户指南中有一个例子(和更多信息),我在这里复制:
POJO with JAXB annotations:
与JAXB注解的POJO:
@XmlRootElement
public class Planet {
public int id;
public String name;
public double radius;
}
Resource:
资源:
@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);
}
}
The xml that gets produced/consumed:
生成/消费的xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<planet>
<id>1</id>
<name>Earth</name>
<radius>1.0</radius>
</planet>
#5
0
It does seem you would have to use a MessageBodyReader
here. Here's an example, using jdom:
你似乎需要在这里使用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
}
}
}
Add this class to the list of resources your jersey deployment will process (usually configured via web.xml, I think). You can then use this reader in one of your regular resource classes like this:
将这个类添加到您的jersey部署将处理的资源列表中(通常通过web配置)。我认为xml)。然后,您可以在您的常规资源类中使用这个阅读器:
@Path("/somepath") @POST
public void handleXMLData(Document doc) {
// do something with the document
}
I haven't verified that this works exactly as typed, but that's the gist of it. More reading here:
我还没有验证这是否与类型化一样,但这是它的要点。更多阅读:
- http://weblogs.java.net/blog/mhadley/archive/2008/02/integrating_jer_2.html
- http://weblogs.java.net/blog/mhadley/archive/2008/02/integrating_jer_2.html
- http://blogs.oracle.com/sandoz/entry/jersey_and_abdera_with_a
- http://blogs.oracle.com/sandoz/entry/jersey_and_abdera_with_a
#1
75
Turns out you don't have to do much at all.
原来你根本不需要做什么。
See below - the parameter x
will contain the full HTTP body (which is XML in our case).
参见下面——参数x将包含完整的HTTP主体(在我们的例子中是XML)。
@POST
public Response go(String x) throws IOException {
...
}
#2
14
You could use the @Consumes annotation to get the full body:
您可以使用@消费注释来获得完整的主体:
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));
}
}
Note: Don't forget the "Content-Type: application/xml" header by the request.
注意:不要忘记请求的“内容类型:应用程序/xml”头。
#3
11
Try this using this single code:
尝试使用这段代码:
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 ...
}
}
The url for try rest services ends .... /serviceX/doSomething
试着rest服务的url ....结束/ serviceX doSomething
#4
6
Since you're transferring data in xml, you could also (un)marshal directly from/to pojos.
由于您正在用xml传输数据,您还可以(un)从/到pojo进行封送。
There's an example (and more info) in the jersey user guide, which I copy here:
泽西用户指南中有一个例子(和更多信息),我在这里复制:
POJO with JAXB annotations:
与JAXB注解的POJO:
@XmlRootElement
public class Planet {
public int id;
public String name;
public double radius;
}
Resource:
资源:
@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);
}
}
The xml that gets produced/consumed:
生成/消费的xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<planet>
<id>1</id>
<name>Earth</name>
<radius>1.0</radius>
</planet>
#5
0
It does seem you would have to use a MessageBodyReader
here. Here's an example, using jdom:
你似乎需要在这里使用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
}
}
}
Add this class to the list of resources your jersey deployment will process (usually configured via web.xml, I think). You can then use this reader in one of your regular resource classes like this:
将这个类添加到您的jersey部署将处理的资源列表中(通常通过web配置)。我认为xml)。然后,您可以在您的常规资源类中使用这个阅读器:
@Path("/somepath") @POST
public void handleXMLData(Document doc) {
// do something with the document
}
I haven't verified that this works exactly as typed, but that's the gist of it. More reading here:
我还没有验证这是否与类型化一样,但这是它的要点。更多阅读:
- http://weblogs.java.net/blog/mhadley/archive/2008/02/integrating_jer_2.html
- http://weblogs.java.net/blog/mhadley/archive/2008/02/integrating_jer_2.html
- http://blogs.oracle.com/sandoz/entry/jersey_and_abdera_with_a
- http://blogs.oracle.com/sandoz/entry/jersey_and_abdera_with_a