2010-08-20 65 views
3

我試圖學習如何使用Jersey編寫REST風格的應用程序和使用Jersey編寫REST風格的應用程序,並且我很努力地理解在將數據發佈到資源時如何處理父/子類型 關係。我使用JSON來交換 數據,但我不認爲這與我的問題特別相關。REST風格的1-N可選關係

的例子中,我與模型工作的員工和團隊 之間的關係。一個僱員可能或可能不,是一個團隊的成員:

GET /team/ - returns a list of teams 
POST /team/ - creates a new team 
GET /team/1 - returns a list of employees in the team with the ID 1 

GET /employee/ - returns a list of employees 
POST /employee/ - creates a new employee 
GET /employee/1 - returns details about the employee with the ID 1 

在這背後我有一些休眠註釋的POJO:一個用於團隊,和一個 爲僱員,以兩者之間的1-N的關係(請記住, 員工可能不是團隊的成員!)。同樣的POJO也註釋 作爲@XmlRootElements使JAXB將允許我將它們傳遞給/從 客戶端爲JSON。

兩個實體的屬性是這樣的:

Team 
    Long id; 
    String name; 
    String desc; 
    List<Employee> employees; 

Employee 
    Long id; 
    Team team; 
    String name; 
    String phone; 
    String email; 

所有好爲止。但我努力理解如何讓僱員通過 正好路過一個團隊的ID,而不是 傳遞嵌套組對象在我的JSON對象中的一個團隊在創建時的成員。

例如,我希望能夠調用POST /員工/用JSON是 看起來是這樣的:

{ 
    "team_id":"1", 
    "name":"Fred Bloggs", 
    "phone":"1234567890", 
    "email":"[email protected]" 
} 

但是,相反,我有這樣的事情經過:

{ 
    "team":{ 
     "id":"1", 
     } 
    "name":"Fred Bloggs", 
    "phone":"1234567890", 
    "email":"[email protected]" 
} 

所以,我的問題是,其他人如何處理在JSON/REST中創建關係而不傳遞整個對象圖?

對不起,這是一個粗略的問題,但正如我所說,我剛剛開始 了,在這個階段術語對我來說是一個問題!

回答

0

REST提供使用的網址作爲參考,太,我覺得這真的很酷的可能性。因此,它應該是這樣的:

{ 
    "team":"http://myapp.com/team/1", 
    "name":"Fred Bloggs", 
    "phone":"1234567890", 
    "email":"[email protected]" 
} 

可避免只是提供一個

{ 
    "team":"1", 
    "name":"Fred Bloggs", 
    "phone":"1234567890", 
    "email":"[email protected]" 
} 

在這種情況下,通過嵌套的對象,也是你的轉換器必須足夠聰明地認爲,如果值了團隊關鍵字是一個字符串(或整數,無論​​作品),而不是另一個JSON對象,它應該被解釋爲一個ID。

1

如果你的框架迫使你的表現,包括奇怪的結構,如{ "id":"1" }話,我會說這是時間切換框架!

更重要的是,而不必擔心加一分的JSONObject你的代碼,我會擔心,術語「1」的確不是一個真正的超鏈接。閱讀超媒體約束或HATEOAS(如果需要)。

要在POST傳遞是什麼:

{ 
    "team_href" : "/teams/1", 
    "name":"can'tbebothered" 
} 

所以服務器看到這個的時候,它只是因爲它承認的(相對)URI鏈接與團隊#1新創建的員工。

1

我會用一個專用的鏈接類型,我仿照它在XML的鏈接標籤,但它會映射到以下JSON:

 

{ 
    ... 
    links: 
    [ 
     { 
      "href" : "/teams/1", 
      "rel" : "team" 
     }, 
     { 
      "href" : "/teams/2", 
      "rel" : "team" 
     } 
    ] 
} 
 

我喜歡上面的鏈接風格,因爲它是更通用的(可以定義關係通過rel屬性)。對我來說,鏈接概念在HTTP REST中非常重要,我爲它奉獻了一種自己的類型。

當心某些情況下,出於性能的考慮(避免網絡調用遍歷鏈接的資源),你需要這樣的內聯關係。爲此,您可以提供一個返回內聯表示/employee/123?inline=true的開關。但只有提供這樣的噱頭,如果真的有必要的話。我曾經這樣做過,但是實現並不是微不足道的(儘管我的格式是XML,它更受限於模式定義)。

0

有多種方式來處理這個問題的解決方案。它是RESTful Web服務領域中的一個類超鏈接問題。由於這與Jersey有關,我建議的第一件事是避免JAXB聚集在一起,因爲JAXB(在XML或JSON環境中)不是HATEOAS。

越來越少了很多與新澤西州和HATEOAS後,我已經來到了意見,對於一個REST風格的WS最好的表示是Atom聯合格式加上JSON。對於你的團隊和員工的例子,我會採取以下方法。

GET /team/ - returns a paginated Atom Syndication Feed list of teams 
POST /team/ - creates a new team receiving a JSON representation 
GET /team/1 - returns a paginated Atom Syndication Feed list of employees in the 
       team with the ID 1 with an Link to team's JSON representation too. 

GET /employee/ - returns a paginated Atom Syndication Feed list of employees 
POST /employee/ - creates a new employee using JSON 
GET /employee/1 - returns details about the employee with the ID 1 in JSON 

直到這裏我沒有改變太多隻是指定一些表示的細節。有趣的部分是添加/刪除團隊中的員工。爲此,我想補充的資源與模式

@Path("/team/{id}/employees) 
class TeamEmployees { 

    @Path("/{posId}") 
    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public Employee get(@PathParam("posId") int positonId) {} 

    @Path("/{posId}") 
    @DELETE 
    public Employee remove(@PathParam("posId") int positonId) {} 

    @POST 
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
    //empUri sample is /employee/{id} server knows how to parse it 
    public Employee add(@FormParam("employeeUri") String empUri) {} 

} 

現在是什麼位置ID,一個方法 - 這是在所有球隊的唯一編號,即在其中將有position_id,TEAM_ID一個表的主鍵,emp_id爲的元組。確保 兩個隊伍永遠不會有2個position_id。這樣整個場景可以變成HATEOAS。

除了能夠在JSON表示導出的URI的DTO,我採取的是方法,我有DTO代表其持久存儲數據模型和我有一個表示表示模型超鏈接(de)可串行化版本DTO其中我將字符串值存儲爲超鏈接。我看表示模型作爲API和DTO作爲SPI REST風格的WS數據模型。