我很享受JAX-RS(特別是Jersey)的自動HTTP內容協商,即它通過「接受」和/或「內容類型」標題來路由我的資源的能力。但是我發現有時在衝突時它不能給我足夠的控制權。JAX-RS/Jersey中的HTTP內容協商衝突?
例如,請考慮以下端點:
@Path("/order")
public class OrderController {
@GET
@Path("{orderID: \\d+}")
@Produces("text/html")
public View getOrderView(@PathParam("orderID") long id) {
Order order = this.getOrderData(id);
return new OrderView(order);
}
@GET
@Path("{orderID: \\d+}")
@Produces({"application/json", "application/xml"})
public Order getOrderData(@PathParam("orderID") long id) {
return new OrderService.findOrder(id);
}
}
我會得到Firefox和Chrome之間不同的結果。 Firefox將映射到HTML端點,而Chrome會在每個端點URL導航時觸發XML端點。它們之間的區別在於Accept頭中列出的MIME類型的順序。 Chrome會將以下內容:
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
對戰在Firefox它首先列出HTML:
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
似乎合乎邏輯,它會在所有加權相同的第一項匹配。但在我的情況下,我得到的結果不盡人意,所以確定一個更好的打破平局的方法會很好。
我的問題:缺少向這些方法注入標題信息和自己執行媒體類型處理,有沒有辦法在配合時「調整權重」?例如,我可以告訴它總是用HTML來勝出XML嗎?我的RESTful客戶非常清楚他們想要回到什麼類型,但瀏覽器在接受頭文件方面出了名。 (我個人認爲他們應該重量HTML略高於XML,因爲這是用戶所期望的,但它是一個有點晚了。)
或者,我可以在一些集中的位置上執行一次自己的自定義內容協商?我不反對手動編寫這個邏輯,但如果這意味着將它應用到我的資源的每一個實例,則不是這樣。 JAX-RS是否有一些在管道中添加過濾器來調整請求的概念?
謝謝,這個Servlet過濾器似乎工作的偉大。有趣的是,我找到了一個結合你兩個建議的人;他正在編寫一個servlet過濾器,以便能夠用Accept頭替換文件擴展名。他的代碼中有一個錯字,因爲他的頭文件檢查區分大小寫。有趣的是:http://www.zienit.nl/blog/2010/01/rest/control-jax-rs-content-negotiation-with-filters – mckamey 2011-03-10 20:48:27
下面是一個修改後的Servlet過濾器,它增加了對文件擴展名的支持並修復了WebKit接受標題排序。 https://gist.github.com/865216 – mckamey 2011-03-11 00:01:07
@mckamey在你寫的評論中的這些增加應該變成一個答案,因爲評論並不意味着永遠生存 – hiergiltdiestfu 2017-01-27 14:47:33