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

为什么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[] { "/*" };
    }
}

其中SpringServletConfig

@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;
    }
}

最后,我在包com中有一个@Controller。实例控制器

@Controller
public class ExampleController {
    @RequestMapping(path = "/home", method = RequestMethod.GET)
    public String example() {
        return "index";
    }
}

我的应用程序的上下文名称是Example。当我向

http://localhost:8080/Example/home

应用程序以HTTP状态404响应,并记录以下内容

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我希望SpringMVC使用我的控制器来处理请求并转发给jsp,那么为什么它会用404来响应呢?

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

共有3个答案

云隐水
2023-03-14

在我的例子中,我遵循5.1.2版本的拦截器Spring留档(同时使用Spring Boot v2.0.4)。RELEASE)和WebConfig类有注释@EnableWebMvc,这似乎与我的应用程序中阻止我的静态资产被正确解析的其他东西相冲突(即没有CSS或JS文件返回到客户端)。

在尝试了很多不同的东西之后,我尝试删除了@EnableWebMvc,它成功了!

编辑:这里的参考留档说您应该删除@EnableWebMvc注释

显然,至少在我的情况下,我已经配置了我的Spring应用程序(尽管不是通过使用web.xml或任何其他静态文件,它肯定是以编程方式),所以这是一个冲突。

隗嘉歆
2023-03-14

除上述情况外,我还解决了我的问题:`

@Bean
public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setPrefix("/WEB-INF/jsps/");
    vr.setSuffix(".jsp");
    return vr;
}

添加了tomcat嵌入jasper:

<dependency>
       <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
       <scope>provided</scope>
</dependency>

`from:JSP文件未在Spring Boot web应用程序中呈现

翟越
2023-03-14

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

DispatcherServlet查看其ApplicationContext,如果可用,则查看向ContextLoaderListener注册的ApplicationContext,以便为特殊bean设置其请求服务逻辑。文档中描述了这些bean。

可以说是最重要的,类型为HandlerMappingmap的bean

对处理程序的传入请求以及基于某些标准的前置和后置处理器(处理程序拦截器)列表,这些标准的详细信息因HandlerMapping实现而异。最流行的实现支持带注释的控制器,但也存在其他实现。

HandlerMapping的javadoc进一步描述了实现必须如何运行。

DispatcherServlet查找此类型的所有bean,并按一定顺序注册它们(可以自定义)。为请求提供服务时,DispatcherServlet循环遍历这些HandlerMapping对象,并使用getHandler测试每个对象,以找到一个可以处理传入请求的对象,表示为标准的HttpServletRequest。截至4.3。x、 如果它没有发现任何警告日志,那么

没有找到HTTP请求与URI的映射[/some/path]DispatcherServlet中的名称

并抛出一个NoHandlerFoundException,或立即提交带有404未找到状态代码的响应。

最常见的HandlerMap实现是刚需MappingHandlerMap,它处理将@Controllerbean注册为处理程序(实际上是它们的@刚需映射带注释的方法)。您可以自己声明这种类型的bean(使用@Bean

  1. @EnableWebMvc注释你的@Configuration类。
  2. 声明一个

正如上面的链接所描述的,它们都将注册一个RequestMappingHandlerMappingbean(以及一堆其他东西)。但是,没有处理程序,HandlerMapping就没有多大用处RequestMappingHandlerMapping需要一些@ControllerBean,因此您也需要通过Java配置中的@Bean方法或

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

springwebmvc库提供了其他内置的HandlerMapping实现。例如,BeanNameUrlHandlerMappingmaps

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

你也可以自己写。显然,您必须确保发送的请求至少与注册的HandlerMapping对象的处理程序中的一个匹配。

如果您没有隐式或显式地注册任何HandlerMappingsbean(或者如果DetectAllHandlerMappingstrue),则DispatcherServlet会注册一些缺省值。这些定义在DispatcherServlet.properties中,与DispatcherServlet类在同一个包中。它们是BeanNameUrlHandlerMapDefaultAnnotationHandlerMap(与相似,但不建议使用)。

SpringMVC将记录通过RequestMappingHandlerMapping注册的处理程序。例如,@控制器类似

@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中指定的所有限制必须匹配,SpringMVC才能选择处理程序。

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

类似地,在DEBUG级别启用Spring日志记录,以查看哪些bean Spring寄存器。它应该报告它找到了哪些带注释的类,它扫描了哪些包,以及它初始化了哪些bean。如果您期望的配置不存在,请查看您的Application ationContext配置。

DispatcherServlet只是一个典型的JavaEEServlet。您可以使用典型的

  • 如何在web中实现Servlet url映射。使用xml

考虑到这一点,一个常见的错误是使用/*的url映射注册DispatcherServlet,从@刚需映射处理程序方法返回视图名称,并期望呈现JSP。例如,考虑一个处理程序方法,如

@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
    return "example-view-name";
}

使用InternalResourceViewResolver

@Bean
public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setPrefix("/WEB-INF/jsps/");
    vr.setSuffix(".jsp");
    return vr;
}

您可能希望将请求转发到路径/WEB-INF/jsps/example view name处的JSP资源。jsp。这不会发生。相反,假设上下文名称为Example,则DisaptcherServlet将报告

在名为“DispatcherServlet”的DispatcherServlet中未找到URI为[/Example/WEB-INF/jsps/Example view name.jsp]的HTTP请求的映射

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

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

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

 类似资料: