1

我正在使用带有 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>

如您所见,没有根元素。所以它把“地址”作为根元素,“地址”元素之后的内容被认为是“额外内容”并显示为错误。

4

1 回答 1

1

最后,我找到了答案,这很简单。我怎么不早点想到呢?我不确定这是否会影响性能。您不需要任何 MessageBodyWriter 或任何东西。只需从org.kkm.test.model复制(不移动) jaxb.properties 文件并将其放在实现包中(即,在org.kkm.test.model.impl中)并添加@XmlRootElement(name="reading" )在实现中(即在 ReadingImpl 中)。如果您想订购,请添加@XmlType(propOrder...

于 2013-07-04T17:47:15.850 回答