rest - 是否可以在 REST 服务的 "post()"方法中提取原始消息正文字符串(即 XML 字符串或 JSON 字符串)?

标签 rest java-8 jax-rs weblogic12c stateless-session-bean

问题:
是否可以在 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/

相关文章:

java - Jersey JSON 不适用于最新的 Jersey API

rest - Groovy Rest Api

reflection - Java8 流式传输类层次结构

java - 何时在 JDK 8+ 中使用 Optional<T> 与 OptionalT(其中 T 是盒装原始类型)?

ejb - @EJB 未注入(inject)到 JAX-RS

javascript - 休息服务 骚扰电话

java.lang.NoClassDefFoundError : Could not initialize class org. jose4j.jwa.AlgorithmFactoryFactory JsonWebSignature getCompactSerialization 错误

java - 如何定义传入 lambda 表达式时将调用哪个重载方法?

java - 如何为 MERGE 语句发送适当的 HTTP 状态?

java - 如何在 JAX-RS 方法中获取 POST 参数?