当前位置: 首页 > 知识库问答 >
问题:

为什么Spring MVC用404响应并报告“DispatcherServlet中没有找到URI为[…]的HTTP请求的映射”?

笪烨
2023-03-14

我正在编写一个部署在Tomcat上的Spring MVC应用程序。请参阅以下最小、完整和可验证的示例

public class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { };
    }
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { SpringServletConfig.class };
    }
    protected String[] getServletMappings() {
        return new String[] { "/*" };
    }
}
@Configuration
@ComponentScan("com.example.controllers")
@EnableWebMvc
public class SpringServletConfig {
    @Bean
    public InternalResourceViewResolver resolver() {
        InternalResourceViewResolver vr = new InternalResourceViewResolver();
        vr.setPrefix("/WEB-INF/jsps/");
        vr.setSuffix(".jsp");
        return vr;
    }
}
@Controller
public class ExampleController {
    @RequestMapping(path = "/home", method = RequestMethod.GET)
    public String example() {
        return "index";
    }
}
http://localhost:8080/Example/home
WARN  o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI `[/Example/WEB-INF/jsps/index.jsp]` in `DispatcherServlet` with name 'dispatcher'

我在/web-inf/jsps/index.JSP上有一个JSP资源,我希望Spring MVC使用我的控制器来处理请求并转发到JSP,那么为什么它用404来响应呢?

这是一个关于这个警告信息的问题的规范帖子。

共有1个答案

程鸿畅
2023-03-14

您的标准Spring MVC应用程序将通过在Servlet容器中注册的DispatcherServlet来服务所有请求。

DispatcherServlet查看它的ApplicationContext以及(如果可用的话)注册在ContextLoaderListener中的ApplicationContext用于设置请求服务逻辑所需的特殊bean。这些bean在文档中进行了描述。

最重要的是handlermapping类型的bean映射

DispatcherServlet查找此类型的所有bean并按某种顺序(可以自定义)注册它们。在为请求提供服务时,DispatcherServlet循环访问这些HandlerMapping对象,并使用GetHandler测试每个对象,以找到能够处理传入请求的对象,表示为标准的HttpServletRequest。从4.3.x开始,如果找不到,它会记录您看到的警告

在名称为SomeName的DispatcherServlet中,未找到URI为[/some/path]的HTTP请求的映射

或者抛出noHandlerFoundException或者立即提交带有404未找到状态代码的响应。

最常见的HandlerMapping实现是RequestMappingHandlerMapping,它处理将@Controllerbean注册为处理程序(实际上是它们的@RequestMapping注释方法)。您可以自己声明这种类型的bean(@bean 或其他机制),也可以使用内置选项。这些建议是:

  1. @enablewebmvc注释@configuration类。
  2. 在XML配置中声明 成员。

正如上面的链接所描述的,这两个都将注册一个RequestMappingHandlerMappingbean(以及一堆其他东西)。但是,如果没有处理程序,handlermapping就不是很有用。RequestMappingHandlerMapping需要一些@controllbean,所以您也需要声明这些bean,可以通过Java配置中的@bean方法,或者XML配置中的 声明,或者通过组件扫描其中的@controll注释类。确保这些豆子在场。

如果您收到警告消息和404并且正确配置了上述所有内容,那么您将请求发送到错误的URI,该URI未被检测到的@requestmapping带注释的处理程序方法处理。

spring-webmvc库提供了其他内置的handlermapping实现。例如,BeannaMeurlHandlerMapping映射

从URL到名称以斜杠(“/”)开头的bean

@Controller
public class ExampleController {
    @RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
    public String example() {
        return "example-view-name";
    }
}

将在信息级别记录以下内容

Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()

这描述了注册的映射。当您看到未找到处理程序的警告时,将消息中的URI与此处列出的映射进行比较。@requestmapping中指定的所有限制都必须匹配,才能使Spring MVC选择处理程序。

其他handlermapping实现记录它们自己的语句,这些语句应该提示它们的映射和相应的处理程序。

    null
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
    return "example-view-name";
}
@Bean
public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setPrefix("/WEB-INF/jsps/");
    vr.setSuffix(".jsp");
    return vr;
}

在名称为“dispatcher”的dispatcherServlet中未找到URI为[/example/web-inf/jsps/example-view-name.jsp]的HTTP请求的映射

因为DispatcherServlet映射到/*并且/*匹配所有内容(除了具有更高优先级的精确匹配),所以将选择DispatcherServlet来处理来自JSTLView(由InternalResourceViewResolver返回)的Forward。几乎在每一种情况下,DispatcherServlet都不会被配置为处理这样的请求。

相反,在这种简单的情况下,您应该将DispatcherServlet注册到/,将其标记为默认servlet。默认servlet是请求的最后一个匹配项。这将允许您的典型servlet容器在尝试使用默认servlet之前选择映射到*.JSP的内部servlet实现来处理JSP资源(例如,Tomcat有jspservlet)。

这就是你在你的例子中看到的。

 类似资料: