RESTJava中的通用响应处理

RESTJava中的通用响应处理,java,rest,jackson,jaxb,jersey,Java,Rest,Jackson,Jaxb,Jersey,我已经创建了REST响应,如下所示 @XmlRootElement(name = "customer_info") @JsonIgnoreProperties(value = { "map" }) public class Customer { private String name; private Integer id; private long time; private Map<String, Object> map = new TreeMap<>(); @Js

我已经创建了REST响应,如下所示

@XmlRootElement(name = "customer_info")
@JsonIgnoreProperties(value = { "map" })
public class Customer {
private String name;
private Integer id;
private long time;
private Map<String, Object> map = new TreeMap<>(); 
@JsonAnyGetter 
public Map<String, Object> getMap() {
    return map;
}

@JsonAnySetter
public void setMap(String name, Object values) { 
    this.map.put(name, values); 
    }
}
还有人可以建议如何修复上述问题吗?
提前感谢。

使用JAXB是不可能的,但是如果您想切换到使用,那么您很容易实现这一点。您所需要做的就是用
@JsonAnyGetter
注释bean中的
Map
getter。这将导致Jackson将映射键序列化为XML中的普通元素。这是一个测试

@Path("jackson-xml")
public class JacksonXmlResource {

    @GET
    @Produces("application/xml")
    public Response get() {
        Model model = new Model();
        model.setProp("foo", "bar");
        model.setProp("name", "Paul");
        return Response.ok(model).build();
    }


    public static class Model {
        private Map<String, Object> props = new HashMap<>();

        @JsonAnyGetter
        public Map<String, Object> getProps() {
            return this.props;
        }

        @JsonAnySetter
        public void setProp(String key, Object value) {
            this.props.put(key, value);
        }
    }
} 
完成这两件事后,它应该会起作用

使用Jackson for XML最酷的一点是,用于JSON的Jackson注释也可以用于XML,比如
@JsonProperty
。Jackson也理解JAXB注释(大多数)。因此,当您从JAXB迁移到Jackson时,您可能只需要保持JAXB注释不变。就道具顺序而言,它不适用于动态特性,仅适用于已定义的特性

另见
  • 如果您想为XML配置Jackson,请看一下,我提到的使用
    ContextResolver

使现代化 如果您不能向项目添加任何新的依赖项,那么另一种方法就是使用标准Java类
org.w3c.dom
API动态创建XML。这将是更冗长和更多的工作,但它会得到你想要的。请参阅以获得一些解释。这里有一个例子。它应该很容易跟随添加的评论

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;


@Path("dom-api")
public class DomXmlResource {

    @GET
    @Produces("application/xml")
    public Response getXml() throws Exception {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

        Document doc = docBuilder.newDocument();

        // create root element
        Element rootEl = doc.createElement("Model");
        doc.appendChild(rootEl);

        Model model = new Model();
        model.setProp("foo", "bar");
        model.setProp("name", "Paul");
        model.setValue("FooBar");

        // set static defined properties
        Element valueEl = doc.createElement("value");
        valueEl.appendChild(doc.createTextNode(model.getValue()));
        rootEl.appendChild(valueEl);

        // set dynamic properties
        for (Map.Entry<String, Object> entry: model.getProps().entrySet()) {
            Element dynamicEl = doc.createElement(entry.getKey());
            dynamicEl.appendChild(doc.createTextNode(String.valueOf(entry.getValue())));
            rootEl.appendChild(dynamicEl);
        }

        // return StreamingOutput so we can just stream the
        // XML results without having to store the String into memory.
        StreamingOutput entity = new StreamingOutput() {
            @Override
            public void write(OutputStream out)
                    throws IOException, WebApplicationException {
                try {
                    // write the XML structure to the output stream.
                    Transformer transformer = TransformerFactory.newInstance()
                            .newTransformer();
                    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                    StreamResult result = new StreamResult(out);
                    DOMSource source = new DOMSource(doc);
                    transformer.transform(source, result);
                    out.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        return Response.ok(entity).build();
    }

    public static class Model {
        private String value;
        private Map<String, Object> props = new HashMap<>();

        public String getValue() {
            return this.value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public Map<String, Object> getProps() {
            return this.props;
        }

        public void setProp(String key, Object value) {
            this.props.put(key, value);
        }
    }
}
import java.io.IOException;
导入java.io.OutputStream;
导入java.util.HashMap;
导入java.util.Map;
导入javax.ws.rs.GET;
导入javax.ws.rs.Path;
导入javax.ws.rs.products;
导入javax.ws.rs.WebApplicationException;
导入javax.ws.rs.core.Response;
导入javax.ws.rs.core.StreamingOutput;
导入javax.xml.parsers.DocumentBuilder;
导入javax.xml.parsers.DocumentBuilderFactory;
导入javax.xml.transform.OutputKeys;
导入javax.xml.transform.Transformer;
导入javax.xml.transform.TransformerFactory;
导入javax.xml.transform.dom.DOMSource;
导入javax.xml.transform.stream.StreamResult;
导入org.w3c.dom.Document;
导入org.w3c.dom.Element;
@路径(“domapi”)
公共类DomXmlResource{
@得到
@生成(“应用程序/xml”)
公共响应getXml()引发异常{
DocumentBuilderFactory docFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder=docFactory.newDocumentBuilder();
Document doc=docBuilder.newDocument();
//创建根元素
Element rootEl=doc.createElement(“模型”);
附录子文档(rootEl);
模型=新模型();
模型.setProp(“foo”、“bar”);
model.setProp(“名称”、“保罗”);
model.setValue(“FooBar”);
//设置静态定义的属性
元素值=doc.createElement(“值”);
appendChild(doc.createTextNode(model.getValue());
根元素。附加元素(Valuel);
//设置动态属性
对于(Map.Entry:model.getProps().entrySet()){
Element dynamicEl=doc.createElement(entry.getKey());
dynamicEl.appendChild(doc.createTextNode(String.valueOf(entry.getValue()));
附加子对象(dynamicEl);
}
//返回StreamingOutput,这样我们就可以对
//无需将字符串存储到内存中即可生成XML结果。
StreamingOutput实体=新StreamingOutput(){
@凌驾
公共无效写入(OutputStream out)
抛出IOException、WebApplicationException{
试一试{
//将XML结构写入输出流。
Transformer Transformer=TransformerFactory.newInstance()
.新变压器();
transformer.setOutputProperty(OutputKeys.INDENT,“是”);
StreamResult结果=新的StreamResult(输出);
DOMSource=新的DOMSource(doc);
变换(源、结果);
out.flush();
}捕获(例外e){
e、 printStackTrace();
}
}
};
返回Response.ok(entity.build();
}
公共静态类模型{
私有字符串值;
私有映射props=newhashmap();
公共字符串getValue(){
返回此.value;
}
公共void设置值(字符串值){
这个值=值;
}
公共地图getProps(){
归还这个道具;
}
public void setProp(字符串键、对象值){
this.props.put(键、值);
}
}
}

使用JAXB是不可能的,但是如果您想切换到使用,那么您很容易实现这一点。您所需要做的就是用
@JsonAnyGetter
注释bean中的
Map
getter。这将导致Jackson将映射键序列化为XML中的普通元素。这是一个测试

@Path("jackson-xml")
public class JacksonXmlResource {

    @GET
    @Produces("application/xml")
    public Response get() {
        Model model = new Model();
        model.setProp("foo", "bar");
        model.setProp("name", "Paul");
        return Response.ok(model).build();
    }


    public static class Model {
        private Map<String, Object> props = new HashMap<>();

        @JsonAnyGetter
        public Map<String, Object> getProps() {
            return this.props;
        }

        @JsonAnySetter
        public void setProp(String key, Object value) {
            this.props.put(key, value);
        }
    }
} 
完成这两件事后,它应该会起作用

使用Jackson for XML最酷的一点是,用于JSON的Jackson注释也可以用于XML,比如
@JsonProperty
。Jackson也理解JAXB注释(大多数)。因此,当您从JAXB迁移到Jackson时,您可能只需要保持JAXB注释不变。就道具顺序而言,它不适用于动态特性,仅适用于已定义的特性

另见
  • 如果您想为XML配置Jackson,请看一下,我提到的使用
    ContextResolver

使现代化 如果您不能向项目添加任何新的依赖项,那么另一种方法就是使用标准Java类
org.w3c.dom
API动态创建XML。这将是更冗长和更多的工作,
<bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>
<bean class="com.dummy.CustomerService"/>
<bean class="com.dummy.Service2"/>
<bean class="com.dummy.Service3"/>
 "org.codehaus.jackson:jackson-core-asl:1.9.2",
    "org.codehaus.jackson:jackson-jaxrs:1.9.2",
    "org.codehaus.jackson:jackson-mapper-asl:1.9.2", 
    "org.codehaus.jackson:jackson-xc:1.9.2",
    "com.sun.jersey:jersey-client:1.12",
    "com.sun.jersey:jersey-core:1.12",
    "com.sun.jersey:jersey-json:1.12",
    "com.sun.jersey:jersey-server:1.12",
    "com.sun.jersey:jersey-servlet:1.12",
    "org.codehaus.jettison:jettison:1.1",
    "javax.ws.rs:jsr311-api:1.1.1",
    "com.sun.jersey.contribs:jersey-apache-client:1.12",
    "com.sun.jersey.contribs:jersey-apache-client4:1.12",
    "com.sun.jersey.contribs:jersey-multipart:1.12",
    "com.sun.jersey:jersey-client:1.12",
    "com.sun.jersey:jersey-core:1.12",
    "com.sun.jersey:jersey-json:1.12",
    "javax.ws.rs:jsr311-api:1.1.1",
    "org.codehaus.jackson:jackson-core-asl:1.9.2",
    "org.codehaus.jackson:jackson-jaxrs:1.9.2",
    "org.codehaus.jackson:jackson-mapper-asl:1.9.2",
    "org.codehaus.jackson:jackson-xc:1.9.2",
    "javax.servlet:javax.servlet-api:3.1.0",
   "org.eclipse.jetty:ecs-jetty-server:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-util:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-servlet:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-servlets:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-http:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-security:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-io:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-continuation:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-deploy:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-webapp:9.4.0.v20161208",
   "org.eclipse.jetty:jetty-xml:9.4.0.v20161208"
@Path("jackson-xml")
public class JacksonXmlResource {

    @GET
    @Produces("application/xml")
    public Response get() {
        Model model = new Model();
        model.setProp("foo", "bar");
        model.setProp("name", "Paul");
        return Response.ok(model).build();
    }


    public static class Model {
        private Map<String, Object> props = new HashMap<>();

        @JsonAnyGetter
        public Map<String, Object> getProps() {
            return this.props;
        }

        @JsonAnySetter
        public void setProp(String key, Object value) {
            this.props.put(key, value);
        }
    }
} 
public AppConfig extends ResourceConfig {
    public AppConfig() {
        register(JacksonJaxbXMLProvider,class);
    }
}
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;


@Path("dom-api")
public class DomXmlResource {

    @GET
    @Produces("application/xml")
    public Response getXml() throws Exception {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

        Document doc = docBuilder.newDocument();

        // create root element
        Element rootEl = doc.createElement("Model");
        doc.appendChild(rootEl);

        Model model = new Model();
        model.setProp("foo", "bar");
        model.setProp("name", "Paul");
        model.setValue("FooBar");

        // set static defined properties
        Element valueEl = doc.createElement("value");
        valueEl.appendChild(doc.createTextNode(model.getValue()));
        rootEl.appendChild(valueEl);

        // set dynamic properties
        for (Map.Entry<String, Object> entry: model.getProps().entrySet()) {
            Element dynamicEl = doc.createElement(entry.getKey());
            dynamicEl.appendChild(doc.createTextNode(String.valueOf(entry.getValue())));
            rootEl.appendChild(dynamicEl);
        }

        // return StreamingOutput so we can just stream the
        // XML results without having to store the String into memory.
        StreamingOutput entity = new StreamingOutput() {
            @Override
            public void write(OutputStream out)
                    throws IOException, WebApplicationException {
                try {
                    // write the XML structure to the output stream.
                    Transformer transformer = TransformerFactory.newInstance()
                            .newTransformer();
                    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                    StreamResult result = new StreamResult(out);
                    DOMSource source = new DOMSource(doc);
                    transformer.transform(source, result);
                    out.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        return Response.ok(entity).build();
    }

    public static class Model {
        private String value;
        private Map<String, Object> props = new HashMap<>();

        public String getValue() {
            return this.value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public Map<String, Object> getProps() {
            return this.props;
        }

        public void setProp(String key, Object value) {
            this.props.put(key, value);
        }
    }
}