2013-03-01 36 views
5

假设Animal是我项目中的一个抽象类,并且我有一个REST资源(在JAX-RS服务器上,使用Jackson进行(反)序列化)一个PUT来操纵存储在我的数据库中的动物。他们有具体的类型,剩下的资源规定请求的路径类型:Jackson和JAX-RS:根据@PathParam类型解析抽象类型

@PUT 
@Consumes(MediaType.APPLICATION_JSON) 
@Path("/{entityType}/{id: \\d+}") 
public <T extends Animal> void putAnimal(@PathParam("entityType") String entityType, @PathParam("id") String id, Animal input) throws IOException { 
    //... 
} 

我想用entityType挑水泥类(DogCat或任何反序列化,为entityTypedogcat或其他)。对于这里解释太复杂的原因,我在不能把类型信息放在JSON输入本身。

所以AIUI注释Animal用自定义TypeIdResolver或类似的东西不能帮助我,因为类型信息不会在JSON本身(这是类型解析器将获得的所有信息)。我打算使用自定义的MessageBodyReader,但据我所知,这不会从其方法readValue中传递的正文中获取其他参数值,所以我不知道要反序列化成什么。

我错过了什么?如果这种方法失败了,我怎么才能完成我想要的,而不需要指定特定于动物的端点(这会导致大量重复的代码以及失去通用性 - 现在我可以添加Animal的子类,并且此代码将工作正常,这是非常好的。)

回答

4

JAX-RS规范(5.2.2 URI和URI模板)的以下引用表明您应该能够将UriInfo实例注入到您的自定义MessageBodyReader中,并使用它的一种方法检查请求的URL路径。

可以使用@Context注释将UriInfo的实例注入到类字段或方法参数中。 UriInfo提供关于请求URI的组件的静态和动态的每个请求信息。

示例只要示出了资源的方法接收UriInfo参数,但通常应该是可以注入的实例,以提供者(MessageBodyReader)为好。

通过UriInfo获得entityType路径参数后,您的MessageBodyReader应该能够提供相应的子类Animal

+0

经过测试,第一次工作完美无瑕。太棒了,非常感谢! – Gijs 2013-03-04 13:53:42

0

鉴于你正在尝试做的,你是关闭构建AnimalResource类,其中包含您的基本方法更好,然后要建立单独的DogResourceCatResource什么任何其他你需要的类延伸AnimalResource。这将允许您获得Animal的正确子类,并正确反序列化输入JSON。

更新 一个如何实现的例子。你的基础资源看起来是这样的:

public class AnimalResource<T extends Animal> 
{ 
    private final transient AnimalService<T> service; 

    public AnimalResource(final AnimalService<T> service) 
    { 
     this.service = service; 
    } 

    @Get 
    @Path("{id}") 
    @Produces(MediaType.APPLICATION_JSON) 
    public T getbyId(@PathParam("id") final String id) 
    { 
     return this.service.findById(id); 
    } 

    // Other CRUD methods go here 
} 

然后你的动物个体,假设它们都具有相同的设置,只是:

@Path("/cats") 
public class CatResource extends AnimalResource<Cat> 
{ 
    public CatResource(final CatService catService) 
    { 
     super(catService); 
    } 
} 

的宠物猫和

@Path("/dogs") 
public class DogResource extends AnimalResource<Dog> 
{ 
    public DogResource(final DogService dogService) 
    { 
     super(dogService); 
    } 
} 

为狗。他们将继承父母的标准CRUD方法,并且任何动物特定的方法仍然可以在个人类中使用。

+0

正如我在问题中已经说过的那样,这将导致重复的代码和通用性的丧失。你还没有指定_why_我比现在的做法更好。这在这个项目中也不是很实用,因为我们将在运行时添加动物。在运行时添加JAX-RS资源是没有意义的。 – Gijs 2013-03-02 20:00:20

+0

首先,如果你有具体的子类,那么就不会有重复的代码,但这不是你的主要问题。根据您创建子类(javassist?)的方式,您可能会或可能无法将它们与ObjectMapper一起使用,但无论您应该考虑构建过滤器。过滤器可以访问完整请求,决定类型,解析输入并存储对象,以便您可以在资源中检索它。虽然... – jgm 2013-03-02 20:58:07

+0

如果有具体的子类,AIUI的方法会导致1-1相应的资源类,除了's/cat/dog /'之外,它们是相同的。重复代码给我。是的,它的手册是我想要避免的。 :-) – Gijs 2013-03-04 10:58:05