我正在使用带有 Jersey 和 Moxy 的 Tomcat 7。我使用 maven 添加了 jersey.server.jar、jersey.servlet.jar、jersey-core.jar、moxy(org.eclipse.persistence.moxy,版本 2.5.0)。
我有接口(包名:org.kkm.test.model):
public interface Model extends BaseModel {
public String getConsumerId();
public void setConsumerId(String consumerId);
}
@XmlRootElement(name="reading")
@XmlType(propOrder={"consumerId", "address", "reading", "readingDate", "rotation", "readingStatus"})
public interface Reading extends Model {
@XmlElement
public Address getAddress();
@XmlElement
public double getReading();
@XmlElement
public Date getReadingDate();
@XmlElement
public short getRotation();
@XmlElement
public ReadingStatus getReadingStatus();
public void setAddress(Address address);
public void setReading(double reading);
public void setReadingDate(Date readingDate);
public void setRotation(short rotation);
public void setReadingStatus(ReadingStatus readingStatus);
}
public interface Address {
public String getAddress1();
public String getAddress2();
public String getAddress3();
public String getAddress4();
public void setAddress1(String address1);
public void setAddress2(String address2);
public void setAddress3(String address3);
public void setAddress4(String address4);
}
我有 ReadingImpl 和 AddressImpl 的实现(包名:org.kkm.test.model.impl)。我有一个服务类如下:
@Path("/sample")
public class TestService {
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/readings")
public List<Reading> getReadings() {
Reading reading1 = DependencySupplier.getReading();
Address address = DependencySupplier.getAddress();
address.setAddress1("Moolekkadavil");
address.setAddress2("Kottuvallikad");
address.setAddress3("Moothakunnam.P.O");
address.setAddress4("683516");
reading1.setAddress(address);
reading1.setConsumerId("1234567890");
reading1.setReading(11.00);
reading1.setReadingDate(new Date());
reading1.setReadingStatus(ReadingStatus.BILLED);
reading1.setRotation((short) 1);
Reading reading2 = DependencySupplier.getReading();
reading2.setAddress(address);
reading2.setConsumerId("1234567890");
reading2.setReading(11.00);
reading2.setReadingDate(new Date());
reading2.setReadingStatus(ReadingStatus.BILLED);
reading2.setRotation((short) 1);
List<Reading> list = new ArrayList<Reading>();
list.add(reading1);
list.add(reading2);
return list;
}
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/reading")
public Reading getReading() {
Reading reading1 = DependencySupplier.getReading();
Address address = DependencySupplier.getAddress();
address.setAddress1("Moolekkadavil");
address.setAddress2("Kottuvallikad");
address.setAddress3("Moothakunnam.P.O");
address.setAddress4("683516");
reading1.setAddress(address);
reading1.setConsumerId("1234567890");
reading1.setReading(11.00);
reading1.setReadingDate(new Date());
reading1.setReadingStatus(ReadingStatus.BILLED);
reading1.setRotation((short) 1);
return reading1;
}
}
我在 org.kkm.test.model 中放置了一个 jaxb.properties 文件,内容如下,以便可以使用 moxy:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
我的 web.xml 是:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Test JAX</display-name>
<servlet>
<servlet-name>testjax</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.kwa.test.service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>testjax</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
我面临的问题是:当我调用“/rest/sample/readings”时,我得到了正确的 XML 表示,但是当我调用“/rest/sample/reading”时,我得到了
com.sun.jersey.api.MessageException:Java 类的消息正文编写器...等错误。
然后我写了一个MessageBodyWriter如下:
public class MyMessageBodyWriter implements MessageBodyWriter {
private List<Class<?>> types;
public MyMessageBodyWriter() {
types = new ArrayList<Class<?>>();
types.add(ReadingImpl.class);
}
public long getSize(Object obj, Class type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
// TODO Auto-generated method stub
return -1;
}
public boolean isWriteable(Class type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return this.types.contains(type);
}
public void writeTo(Object target, Class type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap headers, OutputStream outputStream)
throws IOException, WebApplicationException {
try {
JAXBContext ctx = JAXBContext.newInstance(type);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(target, outputStream);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
}
现在,当我调用“/rest/sample/reading”时,我得到以下 XML:
<?xml version="1.0" encoding="UTF-8"?>
<address>
<address1>Moolekkadavil</address1>
<address2>Kottuvallikad</address2>
<address3>Moothakunnam.P.O</address3>
<address4>683516</address4>
</address><consumerId>1234567890</consumerId><reading>11.0</reading><readingDate>2013-07-04T21:16:39.128</readingDate><readingStatus>BILLED</readingStatus><rotation>1</rotation>
如您所见,没有根元素。所以它把“地址”作为根元素,“地址”元素之后的内容被认为是“额外内容”并显示为错误。