Spring Boot REST -即使使用唯一的路径变量,也会产生歧义映射



我有两个端点,它们具有不同的路径变量集。除非我在URL中提供一个可选参数(name),否则它们都可以工作。然后Spring给出模棱两可的错误。

可选参数name也出现在第二个端点中,这就是发生错误的原因。

为什么Spring认为这些端点是模糊的?

必需的参数应该使端点唯一(因为第一个端点包含参数"sourceid")而第二个则没有)。下面的URL给出了错误:

/? sourceid = 999, applicantid = 1, startingdate = 2020, endingdate = 2021,name = mobileapp

第一端点:

@GetMapping(value = "/", params= {"sourceid", "applicantid", "startingdate", "endingdate"})
public List<Event> getEventsById(
@RequestParam("sourceid") String sourceid,
@RequestParam("applicantid") String applicantid,
@RequestParam("startingdate") String startingdate,
@RequestParam("endingdate") String endingdate,
@RequestParam(value = "name", required = false) String name) {

第二个端点:

@GetMapping(value = "/", params= { "name", "applicantid", "startingdate", "endingdate"})
public List<Event> getEventsByApplicantId(
@RequestParam("applicantid") String applicantid,
@RequestParam("name") String name,
@RequestParam("startingdate") String startingdate,
@RequestParam("endingdate") String endingdate) {

错误信息:

java.lang.IllegalStateException: Ambiguous handler methods mapped for '/event-example/': {public java.util.List com.eventrest.controller.MyController.getEventsById(java.lang.String,java.lang.String,java.lang.String,java.lang.String) throws java.text.ParseException, public java.util.List com.eventrest.controller.MyController.getEventsByApplicantId(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String) throws java.text.ParseException}
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:413) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:367) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:110) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:59) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:396) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1234) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1016) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.38.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.38.jar:4.0.FR]

Spring无法区分请求GEThttp://localhost:8080/?sourceid=999&applicantid=1&startingdate=2020&endingdate=2021&name=mobileapp将由getEventsById()处理还是由getEventsByApplicantId()处理,因为您的映射是模糊的。

考虑第二个方法中的sourceidrequired = false在第一个方法中,这两种方法自然是一样的。

有办法摆脱歧义。

可以根据请求参数条件缩小请求映射。您可以测试是否有请求参数(myParam),是否没有请求参数(!myParam),或者是否有特定的值(myParam=myValue)。阅读参考

!sourceid添加到params字段在您的getEventsByApplicantId()方法中,如下所示:

@GetMapping(value = "/", params= {"!sourceid", "name", "applicantid", "startingdate", "endingdate"})
public List<Event> getEventsByApplicantId(
@RequestParam("applicantid") String applicantid,
@RequestParam("name") String name,
@RequestParam("startingdate") String startingdate,
@RequestParam("endingdate") String endingdate) {
// ..
}

最新更新