[英]How to set priority to Spring-Boot request mapping methods
我有一個帶有 RestController 的 Spring-Boot (v2.0.2) 應用程序,它有 2 種方法,它們的區別僅在於 Accept 標頭。 代碼的簡化版本是這樣的:
@RestController
@RequestMapping("/myapp")
public class FooController {
@GetMapping(value = "/foo/{id}", headers = "Accept=application/json", produces = "application/json;charset=UTF-8")
public ResponseEntity<String> fooJson(@PathVariable id) {
return foo(pageId, true);
}
@GetMapping(value = "/foo/{id}", headers = "Accept=application/ld+json", produces = "application/ld+json;charset=UTF-8")
public ResponseEntity<String> fooJsonLd(@PathVariable id) {
return foo(pageId, false);
}
private ResponseEntity<String> foo(String id, boolean isJson) {
String result = generateBasicResponse(id);
if (isJson) {
return result
}
return addJsonLdContext(result);
}
這工作正常。 例如,如果我們發送一個帶有接受頭的請求,例如application/json;q=0.5,application/ld+json;q=0.6
,它將返回一個 json-ld 響應。
我的問題是,如果我們發送一個沒有接受標頭、空接受標頭或通配符*/*
的請求,那么它默認總是返回一個 json 響應,而我希望默認響應是 json-ld。
我嘗試了各種方法來使 json-ld 請求映射優先於 json 映射:
Accept=*/*
作為第二個接受標頭添加到 json-ld 映射確實可以為其提供優先權,但具有不需要的副作用,即所有接受標頭都被接受,即使是不受支持的類型,例如application/xml
。我能想到的唯一解決方案是創建一個接受兩個標頭的請求映射方法,然后自己處理接受標頭,但我並不喜歡這種解決方案。 有沒有更好、更簡單的方法來優先使用 json-ld?
在對配置自定義 MediaTypes 的這個問題進行了更多搜索之后,我指出了正確的方向。 WebMvcConfigurerAdapter (Spring 3 or 4) 或 WebMvcConfigurer (Spring 5) 允許你像這樣設置默認的媒體類型:
public static final String MEDIA_TYPE_JSONLD = "application/ld+json";
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.valueOf(MEDIA_TYPE_JSONLD));
}
}
這對於沒有或空的接受頭的請求非常有用,以及accept: */*
。 但是,當您將不受支持的類型與通配符結合使用時,例如accept: */*,text/plain
它將返回 json 而不是 json-ld!? 我懷疑這是 Spring 中的一個錯誤。
我使用@GetMapping
注釋中的consumes
解決了這個問題。 根據官方文檔:
格式是單個媒體類型或一系列媒體類型,只有當 Content-Type 匹配這些媒體類型之一時才會映射請求。 可以使用“!”否定表達式運算符,如“!text/plain”,它匹配所有內容類型不是“text/plain”的請求。
在下面的解決方案中,請注意我已將消耗數組添加到普通的 json 請求映射中,這使得客戶端只能使用具有正確Content-Type
的 json 端點。 其他請求轉到ld+json
端點。
@GetMapping(value = "/json", headers = "Accept=application/json", consumes = {"application/json"})
@ResponseBody
public String testJson() {
return "{\"type\":\"json\"}";
}
@GetMapping(value = "/json", headers = "Accept=application/ld+json")
@ResponseBody
public String textLDJson() {
return "{\"type\":\"ld\"}";
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.