2013-03-01 79 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