【问题标题】:Rest Easy, How to accept XML / JSON requests as Source document object in post methodRest Easy,如何在 post 方法中接受 XML/JSON 请求作为源文档对象
【发布时间】:2015-04-14 08:20:00
【问题描述】:

我要做的是,如果客户端在 post 中发送 JSON 或 XML,它应该呈现为源文档参数?

@POST
Response doPost(Source source){
}

任何想法。我尝试查看 MessageBodyReader/Writer 一些拦截方法,但似乎没有任何效果,我相信 3.0.10 Resteasy 不再支持 MessageBodyReader

【问题讨论】:

    标签: xml json rest jax-rs resteasy


    【解决方案1】:

    默认情况下,JAXB 提供程序支持 XML。这意味着您需要 Source 类的 JAXB 注释,并遵循适用于 JAXB 注释/映射的任何其他规则

    @XmlRootElement
    public class Source {
        ....
    }
    

    “我相信 3.0.10 Resteasy 不再支持 MessageBodyReader。”

    实际上这是一个必须支持的 JAX-RS 类/接口/提供程序,。通常使用 Jackson 提供程序,MessageBodyReaderMessageBodyWriter

    如果你使用的是 Maven,你可以简单地添加这个依赖

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    

    并且提供者应该会自动注册。

    如果您不使用 Maven,请获取所有这些 jars

    它们都应该包含在Resteasy distribution 中(尽管链接没有显示 3.0.10 下载 - 不确定从哪里获得)


    更新

    因此,随着 OP 的进一步澄清,要求是能够使用javax.xml.transform.stream.StreamSource

    您可以编写自定义MessageBodyReader,并在那里创建StreamSource 并返回它。例如

    MessageBodyReader

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Type;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.WebApplicationException;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.MultivaluedMap;
    import javax.ws.rs.ext.MessageBodyReader;
    import javax.ws.rs.ext.Provider;
    import javax.xml.transform.stream.StreamSource;
    
    @Provider
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public class StreamSourceMessageBodyReader implements MessageBodyReader<StreamSource> {
    
        @Override
        public boolean isReadable(Class<?> type, Type t, Annotation[] antns, MediaType mt) {
            return type.isAssignableFrom(StreamSource.class);
        }
    
        @Override
        public StreamSource readFrom(Class<StreamSource> type, Type type1, 
                Annotation[] antns, MediaType mt, MultivaluedMap<String, String> mm, 
                InputStream in) throws IOException, WebApplicationException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            return new StreamSource(reader);
        }   
    }
    

    资源

    @Path("source")
    public class SourceResource {
    
        @POST
        @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
        public Response postSource(StreamSource source) throws Exception {
            StringBuilder builder = new StringBuilder("Response=");
            try (BufferedReader reader = (BufferedReader) source.getReader()) {
                String line = null;
                while ((line = reader.readLine()) != null) {
                    builder.append(line).append("\n");
                }
            }
            return Response.ok(builder.toString()).build();
        }
    }
    

    应用配置

    @ApplicationPath("/api")
    public class RestApplication extends Application {
    
        @Override
        public Set<Class<?>> getClasses() {
            Set<Class<?>> classes = new HashSet<>();
            classes.add(SimpleResource.class);
            classes.add(SourceResource.class);
            return classes;
        }
    
        @Override
        public Set<Object> getSingletons() {
            Set<Object> singletons = new HashSet<>();
            singletons.add(new StreamSourceMessageBodyReader());
            return singletons;
        }
    }
    

    测试

    $ curl -X POST -H "Content-Type:application/json" -d '{"hello":"world"}' http://localhost:8080/api/source
    结果:
    Response={"hello":"world"}

    【讨论】:

    • 谢谢@peeskillet,但这并不是我问的那么容易的事情。如果只是我想要一个自定义 JAXB 对象,我就不会问这个问题。我希望你知道 Source 是一个 JavaX SourceStream 文档对象。
    • 基本上我想要的是,我想在资源中的 post 方法处理请求之前拦截请求并基于媒体类型,我想将 json 或 xml 格式的数据转换为 StreamSource对象,然后应该将其作为变量传递给 post 方法。
    • 你应该提到这一点。您可以编写自定义MessagBodyReader,或者简单地接受InputStream,并在方法中从InputStream 创建一个StreamSource。如果你想写一个MessageBodyReader,它就像在StreamSource 中包装InputStream 参数并返回它一样简单
    • @AjeetSingh 查看我的更新
    猜你喜欢
    • 2014-07-04
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2012-03-06
    • 2020-06-17
    • 2018-08-23
    相关资源
    最近更新 更多