在RESTful JAX-RS Apache CXF中实现超媒体

时间:2015-02-17 18:08:02

标签: rest cxf jax-rs

我正在使用Apache CXF开发的RESTful应用程序工作,我想向其介绍超媒体功能。

我们的大多数jaxrs:serviceBeans都遵循以下模板:

@GET
@Path("/{exampleId}")
public ExampleJSON get(@PathParam("exampleId") Integer exampleId) {
    ExampleJSON example;
    // Load data from repository here...

    // Add link to self.
    String href = javax.ws.rs.core.Link.fromResource(ExampleService.class).build().getUri().toString();

    // HypermediaLink is a custom object to hold a "href" and "rel" strings
    HypermediaLink linkToSelf = new HypermediaLink();
    linkToSelf.setHref(href + example.getId());
    linkToSelf.setRel("self");

    // Inherited method, just adds a HypermediaLink to a collection in the parent class
    example.addHypermediaLink(linkToSelf);

    // Return JSON compatible object, JACKSON will serialize it nicely.
    return example;
}

这是基本概念。请记住,为简化起见,我简化了此代码;所以,它很容易被理解。

此代码工作正常;但我想知道是否有更好的方法来使用Apache CXF。我对如何加强它有一些想法;但是,它需要一些自定义注释。

我看到一些使用Jersey的例子,但我想坚持使用Apache CXF。

任何帮助都将不胜感激。

由于

1 个答案:

答案 0 :(得分:1)

我会利用JAX-RS和/或Jackson的一些功能来实现序列化级别的链接添加。因此,您不需要为bean本身内的链接指定特定字段。

  • 您可以实现自定义MessageBodyWriter为POJO生成与默认值不同的JSON有效负载(例如)。所以你可以动态添加链接。

    有关详细信息,请参阅此答案:How to write an XML MessageBodyWriter provider with jersey

  • 如果使用Jackson进行序列化,则可以实现自定义序列化程序。请注意,这是通用的,适用于杰克逊所有支持的格式。

    以下是示例代码:

    public class LinkBeanSerializer extends JsonSerializer<SomeBean> {
        @Override
        public void serialize(SomeBean bean, JsonGenerator jgen,
                SerializerProvider provider) throws IOException,
                      JsonProcessingException {
            jgen.writeStartObject();
    
            // Fields
            jgen.writeNumberField("id", bean.getId());
            // Things could be generic using reflection
    
            // Link
            String href = javax.ws.rs.core.Link.fromResource(SomeBean.class).build().getUri().toString();
            HypermediaLink linkToSelf = new HypermediaLink();
            linkToSelf.setHref(href + bean.getId());
            linkToSelf.setRel("self");
            jgen.writeObjectField("hypermediaLink", linkToSelf);
    
            jgen.writeEndObject();
        }
    }
    

    请注意,我们可以使这个序列化程序更通用(类似extends JsonSerializer<Object>

    有关详细信息,请参阅此答案:Processing JSON response using JAX-RS(如何在JAX-RS中注册自定义序列化程序,...)。

  • 也许实现WriterInterceptor可以解决您的问题,但是由于您需要具有字段hypermediaLink,因此会对bean产生影响。拦截器可以负责填补场地。

    有关详细信息,请参阅此答案:Jersey Update Entity Property MessageBodyWriter

IMO更方便的解决方案是第二个。它是透明的,支持杰克逊支持的所有格式。

希望它可以帮到你, 亨利