spring mvc:只要我添加第三个路径变量,就找不到资源

问题描述:

我为我的REST服务器使用Spring MVC。我的pom.xml中的spring.version版本是3.2.1.RELEASE。spring mvc:只要我添加第三个路径变量,就找不到资源

我已经创建了大量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 } 

但是,如果我放弃{resourceCId}从Java代码,并相应地调整我的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客户端(铬邮递员),而不是我的服务器代码的问题。当我通过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 [[email protected]] as "application/json;charset=UTF-8" using [org.springf[email protected]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/{resourceCId}”的控制器之前选择了我的Url。删除DefaultController为我解决了这个问题。现在我的问题是如何保留DefaultController的功能,而不会触发TenderController。

+0

显示一个给出404的示例URL,但您希望通过此方法处理。 –

+0

添加了REST请求(包括失败的以及成功的请求)。 – Fayez

+0

只是为了好玩,从方法的RequestMapping中删除'value =“”''。它不会有什么不同,但这并不意味着它不会。 – digitaljoel

我相信这可能是一个春天的bug,可能会在某些时候被修复。进入完全相同的问题。在我们的例子中,我们能够通过用普通的vanilla servlet替换处理未映射请求的Default Spring Controller来处理这些404s - 关于如何做到这一点的详细信息是here

+0

欢迎使用*,请将链接的关键点添加到您的帖子中。 –