公开bean属性的子集作为REST服务的XML响应

时间:2010-03-03 20:05:06

标签: java web-services rest xml-serialization

我不确定如何最好地解释这一点,所以这可能有点长,请耐心等待。

假设我有一个带有许多属性的java bean:

public interface Customer {
    public String getFirstName();
    public String getLastName();
    public Address getAddress(); // embedded bean with its own properties
    ... // lots more
}

显然,有一个相应的实现,另外还定义了适当的setter(虽然setter可能不会在某些属性的接口中公开)。

有一个服务(POJO接口+实现)定义了一系列可以对客户执行的操作(CRUD,一些find()查询等)。服务是通过Spring引导的,整个过程在本地和通过RMI工作正常。

现在我有一个客户端(iPhone应用程序)需要访问通过上述API公开的小子集功能 - 在服务操作和API属性方面都是子集。我们的想法是通过REST风格的API公开这个子集:

GET /services/customers/1234

返回

<customer>
  <firstName>Homer</firstName>
  <lastName>Simpson</lastName>
  <city>Springfield</city>
</customer>

或者甚至

<customer firstName="Homer" lastName="Simpson" city="Springfield" />

问题是 - 我该怎么做呢?我(简要地)查看了JAXB / CXF / Jersey,看起来我必须定义一个模式,根据它生成一堆类,并将数据从我的API实体复制到这些类。有没有办法避免这一切?

理想情况下,我想在我的API实体中注释相应的属性,并让它们(并且只有它们)自动编组“自动”。如果需要,我可以为Web服务端点编写专用接口/实现;注释现有的会更好。

另一个(更紧迫的)问题是 - 我做了一些愚蠢的事吗?有更简单和/或更好的方法吗?  上次我使用Web服务是Axis 1.1次,上次我使用iPhone时从来没有:-)所以任何指针都会非常感激。

更新澄清 - 我正在寻找最简单的方法来将子集的javabean属性编组为XML(或者JSON可能?) / em>必须编写/生成另一个类来表示所述属性子集。上面的例子过于简单化,实际上API涉及很多类,相当广泛。我确实希望尽可能避免重复。

3 个答案:

答案 0 :(得分:1)

Google搜索jaxb interface似乎表明界面在JAXB中很难处理,如java.net blog post和另一个stackoverflow question所示。

如果您的POJO是一个类而不是一个接口,可能会更容易。我正在使用RESTEasy(另一个JAX-RS实现)和JAXB,我只需要用@XmlRootElement注释我的POJO类。另一方面,我编写了自定义的http客户端代码,以便使用JAXB对相同的带注释的类进行编组/解组(如果可以使用,则可以使用RESTEasy客户端代理框架自动执行)。请注意,我没有定义架构,但是由于我可以控制RESTful Web服务的两个方面,所以我可以逍遥法外。

泽西岛有client API你可能想看看。 CXF还有一个front-end / client API,包括一个类似于RESTEasy的基于代理的机制。

查看 RESTful Java with JAX-RS 一书,其中涵盖了我发现有用的以下内容:

  • REST服务概念
  • 各种实现的概述,包括客户端API支持
  • 代码示例

控制器示例:

@GET
@Produces( { MediaType.APPLICATION_XML })
@Path("/customers/{id}")
public Customer getCustomer(@PathParam("id") int id) {
    ...
    return customer;
}

示例POJO:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
  Address address;
  String name;

  // annotate with XmlTransient to prevent mapping this property/type to XML
  @XmlTransient
  String ssn;
  ...
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Address {
  String planet;
  ...
}

XmlTransient Java doc

答案 1 :(得分:0)

我的首选是使用JAXB注释注释您已经拥有的类,并让绑定编译器根据您已有的类创建模式,方法是对注释的源文件example here运行schemagen

我发现JAXB非常有用,并且很容易用于创建来自java类的模式和来自模式的java类,我在创建用于服务保险策略的Web服务时使用这些模式。

答案 2 :(得分:0)

最简单的方法:使用XML序列化API,例如XStream或Simple,它们是针对您要求的这种POJO到XML类型的问题而制作的。选择子集并切换到属性很简单,如下所示:

class Customer {
    @XStreamAsAttribute
    String firstName;
    @XStreamAsAttribute
    String lastName;
    @XStreamOmitField
    Address address();
}