【问题标题】:spring mvc: resource not found as soon as I add third path variablespring mvc:添加第三个路径变量后找不到资源
【发布时间】:2014-03-17 13:52:36
【问题描述】:

我正在为我的 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 postman)的问题,而不是我的服务器代码。当我通过 curl 发送相同的请求时,我能够得到预期的结果。

更新: 实际上,无论客户端(邮递员、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/{resourceCId}" 的控制器之前选择了我的 Url。删除 DefaultController 为我解决了这个问题。现在我的问题是如何保留 DefaultController 功能而不让它在我的 TenderController 之前被触发。

【问题讨论】:

  • 显示一个给出 404 但您希望被此方法处理的示例 URL。
  • 添加了 REST 请求(失败的和成功的)。
  • 只是为了好玩,从方法的 RequestMapping 中删除 value=""。它不应该产生影响,但这并不总是意味着它不会。
  • 您的日志说明了什么?响应是否仅包含 404 或与之相关的消息?
  • 刚刚对我的问题添加了更新 - 结果表明当请求来自 chrome-postman 时出现了问题。如果我从 curl 发送相同的请求,我会得到预期的结果。

标签: java rest spring-mvc path-variables postman


【解决方案1】:

我相信这可能是一个 Spring 错误,可能会在某个时候得到修复。遇到完全相同的问题。在我们的例子中,我们能够通过用一个普通的普通 servlet 替换处理未映射请求的默认 Spring Controller 来处理 404 来解决这个问题 - 有关如何做到这一点的详细信息是 here

【讨论】:

  • 欢迎使用stackoverflow,请将链接的关键点添加到您的帖子中。
猜你喜欢
  • 2016-06-15
  • 1970-01-01
  • 2015-07-13
  • 2019-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
  • 2015-01-19
相关资源
最近更新 更多