[英]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.