gpt4 book ai didi

java - 为什么Spring MVC会以404响应并报告“在DispatcherServlet中未找到带有URI […]的HTTP请求的映射”?

转载 作者:太空宇宙 更新时间:2023-11-04 13:52:58 27 4
gpt4 key购买 nike

我正在编写部署在Tomcat上的Spring MVC应用程序。请参阅以下minimal, complete, and verifiable example

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


最后,我在包 @Controller中有一个 com.example.controllers

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


我的应用程序的上下文名称为 Example。当我发送请求给

http://localhost:8080/Example/home


该应用程序以HTTP Status 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资源,我希望Spring MVC使用我的控制器来处理请求并转发给JSP,所以为什么它用404响应?



这旨在成为有关此警告消息问题的规范帖子。

最佳答案

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

DispatcherServlet会查看其ApplicationContext,如果有的话,还会向ApplicationContext注册以查找特殊bean的ContextLoaderListener,它需要设置其请求服务逻辑。 These beans are described in the documentation

可以说是最重要的HandlerMapping类型的bean


  向处理程序的传入请求以及预处理程序和后处理程序的列表
  (处理程序拦截器)基于某些标准
  因HandlerMapping实现而异。最受欢迎的实施
  支持带注释的控制器,但存在其他实现
  好。


javadoc of HandlerMapping进一步描述了实现必须如何表现。

DispatcherServlet查找所有此类型的bean,并按一定顺序注册它们(可以自定义)。在处理请求时,DispatcherServlet循环遍历这些HandlerMapping对象,并使用getHandler测试它们中的每个对象,以找到可以处理传入请求的对象,以标准HttpServletRequest表示。从4.3.x版本开始,如果找不到任何内容,则会显示logs the warning


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


并且either抛出NoHandlerFoundException或立即使用404 Not Found状态代码提交响应。

DispatcherServlet为什么没有找到可以处理我的请求的HandlerMapping

最常见的HandlerMapping实现是RequestMappingHandlerMapping,该实现将@Controller bean注册为处理程序(实际上是其@RequestMapping注释的方法)。您可以自己声明这种类型的bean(使用@Bean<bean>或其他机制),也可以使用the built-in options。这些是:


@Configuration注释@EnableWebMvc类。
在您的XML配置中声明一个<mvc:annotation-driven />成员。


正如上面的链接所描述的,这两个都将注册一个RequestMappingHandlerMapping bean(以及其他一些东西)。但是,没有处理程序的HandlerMapping不是很有用。 RequestMappingHandlerMapping需要一些@Controller bean,因此您也需要通过Java配置中的@Bean方法或XML配置中的<bean>声明,或者通过对其中任一带有@Controller注释的类的组件扫描来声明它们。确保这些豆存在。

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

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


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


而且您总是可以自己编写。显然,您必须确保要发送的请求至少与已注册的HandlerMapping对象的处理程序之一匹配。

如果您没有隐式或显式注册任何HandlerMapping bean(或者如果detectAllHandlerMappingstrue),则DispatcherServlet注册一些defaults。这些在DispatcherServlet.properties中与DispatcherServlet类放在同一包中定义。它们是BeanNameUrlHandlerMappingDefaultAnnotationHandlerMapping(类似于RequestMappingHandlerMapping,但已弃用)。

调试

Spring MVC将记录通过RequestMappingHandlerMapping注册的处理程序。例如,类似的@Controller

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


将在INFO级别记录以下内容

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


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

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

同样,在DEBUG级别启用Spring日志记录以查看Spring注册了哪些bean。它应该报告找到的带注释的类,扫描的包以及初始化的bean。如果没有您期望的配置,请检查您的 ApplicationContext配置。

其他常见错误

DispatcherServlet只是典型的Java EE Servlet。您可以使用典型的 <web.xml> <servlet-class><servlet-mapping>声明,或者直接通过 ServletContext#addServlet中的 WebApplicationInitializer或使用Spring boot使用的任何机制来注册它。因此,您必须依赖 Servlet specification中指定的url映射逻辑,请参见第12章。另请参见


How are Servlet url mappings in web.xml used?


考虑到这一点,一个常见的错误是使用 DispatcherServlet的URL映射注册 /*,从 @RequestMapping处理程序方法返回视图名称,并期望呈现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资源的 forwarded。这不会发生。相反,假设上下文名称为 Example,则 DisaptcherServlet将报告


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


由于 DispatcherServlet映射到 /*并且 /*匹配所有内容(精确匹配除外,它们具有更高的优先级),因此将选择 DispatcherServlet来处理 forward中的 JstlView(由 InternalResourceViewResolver)。在几乎每种情况下, DispatcherServlet都不会配置为处理此类请求。

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

这就是您在示例中看到的。

关于java - 为什么Spring MVC会以404响应并报告“在DispatcherServlet中未找到带有URI […]的HTTP请求的映射”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30119810/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com