gpt4 book ai didi

java - 为什么 Spring MVC 响应 404 并报告 "No mapping found for HTTP request with URI [...] in DispatcherServlet"?

转载 作者:IT老高 更新时间:2023-10-28 11:48:31 26 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 状态 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 使用我的 Controller 来处理请求并转发到 JSP,那么为什么它以 404 响应?

这是关于此警告消息的问题的规范帖子。

最佳答案

您的标准 Spring MVC 应用程序将通过 DispatcherServlet 处理所有请求。您已向 Servlet 容器注册。DispatcherServlet看着它的ApplicationContext如果可用,ApplicationContext注册 ContextLoaderListener对于特殊的 bean,它需要设置它的请求服务逻辑。 These beans are described in the documentation .
可以说是最重要的 bean 类型 HandlerMapping map

incoming requests to handlers and a list of pre- and post-processors(handler interceptors) based on some criteria the details of whichvary by HandlerMapping implementation. The most popular implementationsupports annotated controllers but other implementations exists aswell.


javadoc of HandlerMapping 进一步描述了实现必须如何表现。 DispatcherServlet查找此类型的所有 bean 并按某种顺序注册它们(可以自定义)。在处理请求时, DispatcherServlet遍历这些 HandlerMapping对象并使用 getHandler 测试它们中的每一个找到一个可以处理传入请求的,表示为标准 HttpServletRequest .从 4.3.x 开始, 如果没有找到 ,它 logs the warning你看到的

No mapping found for HTTP request with URI [/some/path] in DispatcherServlet with name SomeName


either抛出 NoHandlerFoundException 或立即提交带有 404 Not Found 状态代码的响应。
为什么没有 DispatcherServlet找一个 HandlerMapping那可以处理我的要求吗?
最常见的 HandlerMapping实现是 RequestMappingHandlerMapping , 处理注册 @Controller bean 作为处理程序(实际上是它们的 @RequestMapping 注释方法)。您可以自己声明这种类型的 bean(使用 @Bean<bean> 或其他机制),也可以使用 the built-in options .这些是:
  • 注释您的 @Configuration@EnableWebMvc 一起上课.
  • 声明一个 <mvc:annotation-driven /> XML 配置中的成员。

  • 正如上面的链接所描述的,这两个都将注册一个 RequestMappingHandlerMapping bean (和一堆其他东西)。然而,一个 HandlerMapping没有处理程序就不是很有用。 RequestMappingHandlerMapping期待一些 @Controller beans 所以你也需要声明它们,通过 @Bean Java 配置中的方法或 <bean> XML 配置中的声明或通过 @Controller 的组件扫描两者中的带注释的类。 确保这些 bean 存在。
    如果您收到警告消息和 404,并且您已正确配置上述所有内容, 那么您将请求发送到错误的 URI , 一个未被检测到的 @RequestMapping带注释的处理程序方法。 spring-webmvc库提供其他内置 HandlerMapping实现。例如, BeanNameUrlHandlerMapping map

    from URLs to beans with names that start with a slash ("/")


    而且你总是可以自己写。显然, 您必须确保您发送的请求与已注册的 HandlerMapping 中的至少一个匹配。对象的处理程序。
    如果您没有隐式或显式注册任何 HandlerMapping beans(或者如果 detectAllHandlerMappings true ),则 DispatcherServlet注册一些 defaults .这些定义在 DispatcherServlet.properties 中在与 DispatcherServlet 相同的包中类。他们是 BeanNameUrlHandlerMapping DefaultAnnotationHandlerMapping (类似于 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网址映射为 /* ,从 @RequestMapping 返回 View 名称handler 方法,并期望呈现 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;
    }
    您可能希望请求是 forwarded到路径 /WEB-INF/jsps/example-view-name.jsp 处的 JSP 资源.这不会发生。相反,假设上下文名称为 Example , DisaptcherServlet会报告

    No mapping found for HTTP request with URI [/Example/WEB-INF/jsps/example-view-name.jsp] in DispatcherServlet with name 'dispatcher'


    因为 DispatcherServlet映射到 /*/*匹配所有内容(除了具有更高优先级的精确匹配), DispatcherServlet将被选择来处理 forward来自 JstlView (由 InternalResourceViewResolver 返回)。 在几乎所有情况下,DispatcherServlet不会被配置为处理这样​​的请求 .
    相反,在这种简单的情况下,您应该注册 DispatcherServlet/ ,将其标记为默认 servlet。默认 servlet 是请求的最后一个匹配项。这将允许您的典型 servlet 容器选择一个内部 Servlet 实现,映射到 *.jsp ,在尝试使用默认 servlet 之前处理 JSP 资源(例如,Tomcat 有 JspServlet )。
    这就是您在示例中看到的内容。

    关于java - 为什么 Spring MVC 响应 404 并报告 "No mapping found for HTTP request with URI [...] in DispatcherServlet"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41577234/

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