RESTJava中的通用响应处理
我已经创建了REST响应,如下所示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
@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);
}
}
}