Java 如何设置Spring引导请求映射方法的优先级
我有一个springboot(v2.0.2)应用程序,其中有一个RestController,有两种方法,它们的区别仅在于Accept头。代码的简化版本如下:Java 如何设置Spring引导请求映射方法的优先级,java,spring-boot,spring-restcontroller,request-mapping,content-negotiation,Java,Spring Boot,Spring Restcontroller,Request Mapping,Content Negotiation,我有一个springboot(v2.0.2)应用程序,其中有一个RestController,有两种方法,它们的区别仅在于Accept头。代码的简化版本如下: @RestController @RequestMapping("/myapp") public class FooController { @GetMapping(value = "/foo/{id}", headers = "Accept=application/json", produces = "application/
@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);
}
@RestController
@请求映射(“/myapp”)
公共类FooController{
@GetMapping(value=“/foo/{id}”,headers=“Accept=application/json”,products=“application/json;charset=UTF-8”)
公共响应属性fooJson(@PathVariable id){
返回foo(pageId,true);
}
@GetMapping(value=“/foo/{id}”,headers=“Accept=application/ld+json”,products=“application/ld+json;charset=UTF-8”)
公共响应属性fooJsonLd(@PathVariable id){
返回foo(pageId,false);
}
private ResponseEntity foo(字符串id,布尔isJson){
字符串结果=generateBasicResponse(id);
if(isJson){
返回结果
}
返回addJsonLdContext(结果);
}
这很好。如果我们发送了一个带有accept头的请求,例如application/json;q=0.5,application/ld+json;q=0.6
,它将返回一个json ld响应
我的问题是,如果我们发送的请求没有accept标头、一个空accept标头或一个通配符*/*
,那么默认情况下它将始终返回一个json响应,而我希望默认响应是json ld
我尝试了各种方法使json ld请求映射优先于json请求映射:
- 颠倒映射的声明顺序
- 向这两个方法添加@Order注释(json ld的值为1,json方法的值为2)
- 创建不同的类并将@Order注释置于类级别
- 将
作为第二个Accept头添加到json ld映射中确实有助于为其提供首选项,但会产生不必要的副作用,即所有Accept头都被接受,甚至不受支持的类型,例如Accept=*/*
application/xml
我能想到的唯一解决方案是创建一个同时接受两个头的请求映射方法,然后自己处理接受头,但我真的不喜欢这个解决方案。有没有更好、更简单的方法来优先使用json ld?我使用
@GetMapping
注释中的consumes
解决了这个问题.:
格式为单一媒体类型或一系列媒体类型,仅当内容类型与其中一种媒体类型匹配时,才会映射请求。表达式可以通过使用“!”运算符进行否定,如“!text/plain”,它将所有请求与“text/plain”以外的内容类型匹配
在下面的解决方案中,请注意,我已将consumes数组添加到正常的json请求映射中,使客户端仅能够在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\"}";
}
经过进一步的搜索,我找到了正确的方向。
WebMVCConfigureAdapter(Spring 3或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中的一个错误。谢谢您的回答,但这对您来说不起作用me.传入的请求没有内容类型标头,因此当我将consumes添加到json方法时,任何带有Accept:application/json
标头的请求都将返回406。哦,抱歉!我没有注意到Postman将内容类型标头添加到请求中,伪造了我的结果。我深入研究了这个问题,只有一个wa创建一个过滤器,根据“接受”添加一个“内容类型”标题客户端发送的标题。在我看来,此解决方案非常难看,但适用于应用程序中的所有请求。如果您认为向控制器添加其他方法比此解决方案更糟糕,我可以分享更多详细信息。感谢您的帮助。我实际上找到了一个更好的解决方案,并将其作为答案发布。