问题:
是否可以在 REST 服务的“post()”方法中提取原始消息正文字符串(即 XML 字符串或 JSON 字符串)?
环境
Java 8
WebLogic 12.1.3(带有 jax-rs(2.0,2.5.1) 可部署库)
(“request.getInputStream()”没有产生任何结果...似乎“read()”已经“内部”应用。此外,“mark()”或“reset()”也不是支持)
“post()”方法...
package aaa.bbb.ccc;
import javax.ejb.Stateless;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import aaa.bbb.ccc.fieldslist.FieldsList;
import java.io.*;
import java.net.URI;
import javax.ws.rs.core.*;
import javax.xml.bind.JAXBException;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Stateless
@Path("/fieldsList")
public class Testws {
private static final Logger LOG = LogManager.getLogger(Testws.class);
public Testws() {
}
@POST
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response post(@Context UriInfo uriInfo, @Context javax.servlet.http.HttpServletRequest request, FieldsList fieldsList) throws IOException, JAXBException, Exception {
try {
//...returns empty string...
String s = IOUtils.toString(request.getInputStream(), "UTF-8");
LOG.info("message string from request.getInputStream()=" + s); <== empty string...
} catch (Exception e) {
e.printStackTrace();
}
URI uri = UriBuilder.fromUri(uriInfo.getRequestUri()).build();
Response response = Response.created(uri).build();
return response;
}
}
我尝试使用拦截器(请参阅“aroundReadFrom()”方法)在 post() 方法使用 InputStream 之前对其进行操作,但是没有效果... - 也就是说,在 REST 服务的 post() 方法中, request.getInputStream() 继续没有产生任何结果...
“aroundReadFrom()”方法...
package aaa.bbb.ccc;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Provider
public class MyReaderInterceptor implements ReaderInterceptor {
static final Logger LOG = LogManager.getLogger(MyReaderInterceptor.class);
@Override
public Object aroundReadFrom(ReaderInterceptorContext ctx) throws IOException {
try {
InputStream is = ctx.getInputStream();
byte[] content = IOUtils.toByteArray(is);
is.close();
ctx.setInputStream(new ByteArrayInputStream(content));
return ctx.proceed();
} catch (IOException | WebApplicationException e) {
e.printStackTrace();
}
return null;
}
}
这是测试 xml 消息...:
<?xml version="1.0" encoding="UTF-8"?>
<FieldsList xmlns="http://aaa.bbb.ccc.ws/testws">
<Fields>
<FieldA>fieldA_value</FieldA>
<FieldB>fieldB_value</FieldB>
<FieldC>fieldC_value</FieldC>
</Fields>
</FieldsList>
这是架构:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
targetNamespace="http://aaa.bbb.ccc.ws/testws"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:tw="http://aaa.bbb.ccc.ws/testws"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="FieldsType">
<xs:all>
<xs:element name="FieldA" type="xs:string" minOccurs="0" />
<xs:element name="FieldB" type="xs:string" minOccurs="0" />
<xs:element name="FieldC" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
<xs:element name="FieldsList">
<xs:complexType>
<xs:sequence>
<xs:element name="Fields" type="tw:FieldsType" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
更新:
在 post() 方法中,我只能使用这种技术重建消息字符串...
StringWriter sw = new StringWriter();
JAXBContext.newInstance(FieldsList.class).createMarshaller().marshal(fieldsList, sw);
System.out.println("posted xml string=" + sw.toString());
...但是,如果相同的数据以 JSON 格式发布,这将无济于事。澄清一下,它将把 JSON post 消息重建为 XML 字符串,而不是原始的 JSON 字符串
同样,我想要做的是在 post() 方法中访问原始发布的 XML/JSON 消息字符串
最佳答案
使用请求属性的解决方案 - 测试工作 100%
@Provider
public class ContainerRequestFilterImpl implements ContainerRequestFilter {
@Context
private HttpServletRequest request;
@Override
public void filter(ContainerRequestContext ctx) throws IOException {
InputStream is = ctx.getEntityStream();
byte[] content = IOUtils.toByteArray(is);
// Store content as Request Attribute
request.setAttribute("content", new String(content, "UTF-8"));
ctx.setEntityStream(new ByteArrayInputStream(content));
}
}
AND
@POST
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response post(@Context UriInfo uriInfo, @Context HttpServletRequest request, FieldsList fieldsList) throws IOException, JAXBException, Exception {
try {
String s = request.getAttribute("postContent");
LOG.info("Post content: " + s);
} catch (Exception e) {
e.printStackTrace();
}
}
我认为你可以使用 ReaderInterceptor 而不是 ContainerRequestFilter。它应该也能工作。
关于rest - 是否可以在 REST 服务的 "post()"方法中提取原始消息正文字符串(即 XML 字符串或 JSON 字符串)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41602142/