雖然你已經找到了解決辦法,因爲我的原因不能接受的答案我在下面解釋的忠實粉絲,我會發佈一個答案。誠然,這是一個非常自以爲是的答案,因爲HTTP規範允許多種方式來實現類似的事情,而REST並不規定某種URI風格,也爲語義解釋留下了許多擺動空間。
對於可能的URI參數的語義,超文本傳輸協議(HTTP)不是非常具有描述性。 path
和query
這些參數大家都知道,header
和matrix
參數經常被忽略,儘管JAX-RS(就像您最初要求的RESTeasy一樣)可以像處理其他參數那樣容易地處理它們。
REST此外是一種架構風格而不是協議。要調用服務(或API)RESTful,它必須遵守幾個constraints以及尊重底層的HTTP協議。由於REST是以資源爲導向的,所以使用唯一的資源標識符來調用相應的資源(因此是URI)。但是,REST並未對URI的設計方式施加任何限制。人們傾向於將一些語義上的意義放入一個好的URI中,但對於計算機來說,它只是一個進一步的字符串。
在你的評論中寫道:
我真的不這麼認爲。大多數API都面臨着我所描述的工作(也許我曾與錯誤的工作)。
對我的評論,/entites/{entityId}?where=condition
返回一個指定實體的子集而不是實體的子集。通過在URI中指定{entityId}
作爲路徑參數,您已將結果集限制爲單個實體。如果您打算返回一組符合特定實體屬性的實體,爲什麼還要提供{entityId}
?
查詢參數被附加到URI的末尾,因此與矩陣參數f.e相比,屬於每個單獨的路徑段。它們僅屬於單個路徑段,因此在具有多個路徑段的較長URI上傳遞稍微不同的語義。在不包含子資源的簡單URI上,矩陣參數和查詢參數之間的差異相當小,它們都可以交換使用。不過,對於具有多個路徑段的URI,語義可能會發生變化。
此外,我不明白你的意思是一個實體的子集?
如果您有與ID USER1像下面的一個用戶實體JSON表示:
{
"firstName": "Tim",
"lastName": "Sample",
"address": {
"street": "...",
"zip": "...",
"city": "...",
"country": "..."
}
}
調用GET /user/user1?filter=lastName
我期望的查詢,通過address
F.E.只返回{ "lastName": "Sample" }
,在濾波我希望只有地址子資源才能返回,儘管在這種情況下我會使用/users/user1/address
。類似GET /user/user1?lastName=Sample
可能會被解釋爲檢查,如果識別的用戶具有提供的名稱,因此應返回true或false作爲響應。正如你所看到的,人類在語義上解釋URI或它們的參數,而對於計算機,URI只包含子字符串,並且他們不關心參數是否作爲path-,query-,matrix-或者header參數提供。他們僅僅依靠一些預定義的指令來告訴他們從哪裏提取所需的信息。
我對接受的解決方案的擔憂是,在使用POST
時,您可以直接向服務器發送任何內容。因此,您需要明確記錄需要發送給服務的預期表示以及服務器在接收到請求後執行的行爲。此外,在使用POST
進行查詢時,您將無法緩存響應。後者是REST擁有的few constraints之一。雖然某些緩存框架不會在包含查詢參數的URI上緩存響應,但是this link以及this answer都表明這更像是一個城市傳說,然後是現實。
當然,您可以實現服務器端緩存以儘量減少數據庫查找,但請求仍然會到達服務器。在使用GET而不是POST時,由於客戶端能夠緩存答案(如果不通過特殊響應頭設置阻止),因此請求甚至不會連續到達服務器,因此直接從緩存返回答案而不是查看狀態一次又一次。
但是這將是一個很好的方法,當我們需要獲取特定的實體組,相當於一個SQL SELECT ...其中id在(ID1,ID2 ...)當多個HTTP/GET實體/由於延遲,{entityId}不是一個選項嗎?
如an other post所述,可以在路徑段上指定矩陣參數,而不是在整個URI上指定矩陣參數,如查詢參數。這使得它們對URI的某些部分進行過濾非常有用。如果你想返回f.e.所有由灰色頭髮顏色的教授舉辦的課程可以使用GET /professors;haircolor=grey/courses
之類的內容。你當然可以扭轉結構並使用類似/courses/professors?haircolor=grey
這樣的語法上完全沒問題,但如果你考慮哪些資源可以更容易地存在,而不是更容易使用這些資源,並且在更多的依賴資源之前使用這些資源,那麼最終可能會得到前一個URI。
因此,針對您的問題的可能解決方案可能如下所示:GET /entity;id={id1};id={id2};...
。正如在this answer中所解釋的那樣,在單個資源上使用查詢或矩陣參數可能不會有很大的區別,但是如果你是f.e.想要返回指定用戶組的所有地址,只有您可以使用類似這樣的內容:GET /users;id={id1};id={id2}/addresses
。這允許您在使用HTTP GET時進行響應緩存,同時您還在語義上使用資源子資源語法,其中在引用資源之前使用了更有可能不存在另一個的資源子資源語法。
由於RESTeasy能夠使用JAX-RS,因此可以使用@MatrixParam
批註方便地將矩陣參數注入方法參數。與@QueryParam
或@PathParam
參數一樣,基礎JAX-RS框架將盡力嘗試convert the parameter以盡力而爲。
@GET
public Response getSomething(@MatrixParam List<String> ids) {
...
}
在情況下參數不能被整理到自動的對象,也可以使用@Context
註解注入一個UriInfo
對象,然後經由相應的PathSegment
該參數上註解,然後編組檢索矩陣參數它對你自己的一個對象。
@GET
public Response getSomething(@Context UriInfo info) {
for (PathSegment segment : info.getPathSegments()) {
MultivaluedMap matrixParameters = segment.getMatrixParameters();
...
}
}
由於PathSegment
返回MultivaluedMap
,同樣關鍵的是能像你的情況返回多個值(如列表)要插入到數據庫查詢多個ID。 UriInfo
還提供了查詢路徑和查詢參數的MultivaluedMap
。
因此,您決定使用哪種參數風格,REST並不指定特定的URI設計或語義。雖然我不建議使用POST
,但我建議使用GET
來減少爲了向服務發送查詢所需的文檔開銷,並獲得緩存返回響應的能力。
難道不是另一個條件嗎?爲什麼不使用/實體?id = id1,id2,id3 – sancho21
REST與您的URI設計幾乎沒有任何關係!另外,'/ entities/{entityId}?where = condition'我卑微的意義應該返回一個實體的某個子集,而不是一組實體。 –
@RomanVottner我並不真的看到它那樣。大多數API都面臨着我所描述的工作(也許我曾與錯誤的工作)。另外我不明白你的意思是一個實體的子集? –