简体   繁体   English

Spring 引导 2.3 模糊映射

[英]Spring Boot 2.3 Ambiguous Mapping

I have a spring controller with two endpoints that are returning an arbitrary method exception when they are accessed.我有一个 spring controller 有两个端点,它们在被访问时返回任意方法异常。 I am trying to distinguish between them using the HeaderContentNegotiationStrategy which looks at the Accept header of the incoming request to determine which method to map the request to.我试图使用 HeaderContentNegotiationStrategy 来区分它们,它查看传入请求的 Accept header 以确定将请求发送到 map 的方法。 To my understanding this strategy should compare the incoming accept header with the produces notation.据我了解,此策略应将传入的接受 header 与产生符号进行比较。 In my case both methods do produce an application/json media type, however Spring also lets you provide a consumes which to my reading of their doc , should also have the content negotiation look at the request's Content-Type header to map the method.在我的情况下,这两种方法都会产生一个 application/json 媒体类型,但是 Spring 还允许您提供一个消耗,我阅读他们的文档,还应该让内容协商查看请求的 Content-Type header 到 Z1D78DC8ED512144E0518 方法

My question is, how do I get the content negotiation to look at the Content-Type header as well when doing this mapping?我的问题是,在进行此映射时,如何让内容协商同时查看 Content-Type header? If you cannot get the content negotiator to look at the consumes notation, why is it there?如果您无法让内容协商者查看消费符号,那为什么会出现呢? Whats the point?重点是什么?

Controller: Controller:

@ResourcePayloadOverride(action = ActionTypes.READ)
@CustomPermission(Permission.READ)
@RequestMapping(method = RequestMethod.POST,
        produces = { MediaType.APPLICATION_JSON_VALUE, ResourceCollection.MEDIA_TYPE_JSON_VALUE },
        consumes = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<ResourceCollection<Class1>> method1(
        @PathVariable(value="param_1") String param1,
        @RequestParam(value="param_2", required=false) long param2,
        @RequestParam(value="param_3", required=false) int param3,
        @RequestParam(value="param_4", required=false) String param4,
        @RequestBody(required=false) String body) {
    [...]
}

@RequestMapping(method = { RequestMethod.POST },
        produces = { MediaType.APPLICATION_JSON_VALUE, Class1.MEDIA_TYPE_JSON_VALUE },
        consumes = { Class1.MEDIA_TYPE_JSON_VALUE, Class2.MEDIA_TYPE_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Class1> post(
        @PathVariable("param1") String param1,
        @RequestParam(value="param2", required = false) String param2,
        @RequestParam(value="param3", required = false) String param3,
        @RequestParam(value="param4", required = false) String param4,
        @RequestBody(required=false) String noop) //Actually needed!!!
{
    [...]
}

Error:错误:

{"version":1,"timeStamp":"2021-05-13T16:30:33.785Z","level":"error","source":"","message":"java.lang.IllegalStateException: Ambiguous handler methods mapped for '/{my_endpoint}': {public org.springframework.http.ResponseEntity {myPackage.class}.method1(java.lang.String,long,int,java.lang.String,java.lang.String), public org.springframework.http.ResponseEntity {myPackage.class}.post(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String)}","messageParameters":{"0":"java.lang.IllegalStateException","1":"Ambiguous handler methods mapped for '/{my_endpoint}': {public org.springframework.http.ResponseEntity {myPackage.class}.method1(java.lang.String,long,int,java.lang.String,java.lang.String), public org.springframework.http.ResponseEntity {myPackage.class).post(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String)}"

I've replaced a number of details with dummy values here but I dont believe this should effect the larger question我在这里用虚拟值替换了一些细节,但我认为这不会影响更大的问题

Simplifying the problem: Distinguish an endpoint based on consumes简化问题:根据consumes区分端点


import org.springframework.web.bind.annotation.RequestParam;

@RestController
class ConsumeController {
    @PostMapping(value = "/post", consumes = MediaType.APPLICATION_JSON_VALUE)
    public String postJson(@RequestBody(required = false) String data) {
        return "json: " + data;
    }

    @PostMapping(value = "/post", consumes = MediaType.TEXT_PLAIN_VALUE)
    public String postText(@RequestBody(required = false) String data) {
        return "text: " + data;
    }
}

That will do what is expected when there is actually data provided:当实际提供数据时,这将达到预期的效果:

curl -d "{'x':'y'}" -H "Content-Type:application/json" -X POST http://localhost:8080/post
json: {'x':'y'}

curl -d "hello" -H "Content-Type:text/plain" -X POST http://localhost:8080/post
text: hello

But that won't work when no data is sent:但是当没有数据发送时这将不起作用:

curl -H "Content-Type:application/json" -X POST http://localhost:8080/post
{...error: Ambiguous handler methods mapped for '/post'}

The request cannot be distinguished when there is nothing to consume ...没有东西消费的时候无法区分请求...

Possible workarounds:可能的解决方法:

  • make the data required @RequestBody(required = true) String data and handle empty data使数据成为必需@RequestBody(required = true) String data并处理空数据
  • make your endpoint unique by with an extra header like @PostMapping(value= "/post", consumes = MediaType.TEXT_PLAIN_VALUE, headers="allow=text")使用额外的header使您的端点独一无二,例如@PostMapping(value= "/post", consumes = MediaType.TEXT_PLAIN_VALUE, headers="allow=text")
curl -H "Content-Type:text/plain" -H "allow:text"  -X POST http://localhost:8080/post
text: null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM