springmvc:resource在我添加第三个路径变量时没有找到



我的REST服务器使用Spring MVC。我的pom.xml中的spring.version是3.2.1.RELEASE.

我已经创建了许多RESTful API,并广泛使用了PathVariables。它运行良好。

但它似乎在以下情况下崩溃了。如果我有以下内容,我的REST请求找不到资源。

@Controller
@RequestMapping(value = { "/resourceA/{resourceAId}/resourceB/{resourceBId}/resourceC/{resourceCId}" })
public class TenderController {
@RequestMapping(value = "", method = RequestMethod.POST)
@ResponseBody
public Tender capture(
@PathVariable long resourceAId,
@PathVariable long resourceBId,
@PathVariable long resourceCId,
@RequestBody Map<String, Object> requestBody) {
...
}
}

编辑:

以下是我失败的REST请求示例:

POST /resourceA/1/resourceB/2/resourceC/3 HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Cache-Control: no-cache
{ "bodyParam1": 400, "bodyParam2": 0 }

然而,如果我从Java代码中删除{resourceCId}并相应地调整REST请求,它就会成功地找到资源:

修订Java代码:

@RequestMapping(value = { "/resourceA/{resourceAId}/resourceB/{resourceBId}/resourceC" })

新的(成功的)REST请求:

POST /resourceA/1/resourceB/2/resourceC HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Cache-Control: no-cache
{ "bodyParam1": 400, "bodyParam2": 0 }

所以基本上,只要我有3个路径变量,事情就好像分崩离析了。有什么想法吗?我是否偶然发现了Spring MVC错误?我猜不会,因为3个路径变量应该是一个非常常见的场景(几乎不符合拐角情况)。

更新:这似乎是我的HTTP客户端(chrome poster)的问题,而不是我的服务器代码。当我通过curl发送相同的请求时,我能够得到预期的结果。

更新:实际上,无论客户端(poster、curl等)如何,错误都会返回并发生。所以这肯定是服务器端的问题。这是的日志

01:35:39.409 [http-bio-8080-exec-5] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'mvc-dispatcher' processing POST request for [/resourceA/1/resourceB/1/resourceC/1]
01:35:39.411 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /resourceA/1/resourceB/1/resourceC/1
01:35:39.414 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [public void com.sample.controller.DefaultController.unmappedRequest()]
01:35:39.414 [http-bio-8080-exec-5] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'defaultController'
01:35:39.422 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public void com.sample.controller.DefaultController.unmappedRequest()]: com.sample.exception.APIException: Url pattern is invalid.
01:35:39.423 [http-bio-8080-exec-5] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'globalControllerExceptionHandler'
01:35:39.423 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Invoking @ExceptionHandler method: public com.sample.model.ErrorInfo com.sample.controller.GlobalControllerExceptionHandler.handleAPIException(com.sample.exception.APIException)
01:35:39.460 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Written [com.sample.model.ErrorInfo@df27cd5] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@2ae18b1a]
01:35:39.460 [http-bio-8080-exec-5] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'mvc-dispatcher': assuming HandlerAdapter completed request handling
01:35:39.460 [http-bio-8080-exec-5] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request

发现了导致问题的原因:
所以,在处理了许多不同的事情之后,我发现了导致这个问题的原因。我有一个DefaultController.java,它旨在捕获所有与其他控制器不匹配的Url,并报告在REST服务的错误响应中找不到的漂亮资源。DefaultController具有以下代码:

package com.sample.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.sample.exception.APIException;
import com.sample.exception.APIException.Code;
@Controller
public class DefaultController {
@RequestMapping("/**")
public void unmappedRequest() {
throw new APIException(Code.INVALID_URL_PATTERN,
"There is no resource for this path");
}
}

这对我来说效果很好。但在这种情况下,不知何故,这个DefaultController"/**"在实际设置为接收"/resourceA/{resourceAId}/resourceB/{resourceBId}/resourceC/{sourceCId}"的控制器之前选择了我的Url。删除DefaultController为我解决了这个问题。现在我的问题是,如果不在TenderController之前触发它,我如何才能保留DefaultController功能。

我相信这可能是一个Spring错误,可能会在某个时候得到修复。遇到了完全相同的问题。在我们的案例中,我们能够通过将处理未映射请求的默认Spring控制器替换为处理404的普通servlet来解决这个问题——关于如何做到这一点的详细信息在这里。

最新更新