您的标准 Spring MVC 应用程序将通过DispatcherServlet您已在 Servlet 容器中注册。
The DispatcherServlet
看着它的ApplicationContext
并且,如果有的话,ApplicationContext
注册于ContextLoaderListener
对于特殊的bean,它需要设置其请求服务逻辑。这些 bean 在文档中有描述.
可以说是最重要的,豆类HandlerMapping map
处理程序的传入请求以及预处理器和后处理器的列表
(处理程序拦截器)基于一些标准,其中的细节
因HandlerMapping
执行。最流行的实现
支持带注释的控制器,但其他实现如下
出色地。
The javadoc 的HandlerMapping进一步描述了实现必须如何表现。
The DispatcherServlet
查找该类型的所有 bean 并按某种顺序注册它们(可以自定义)。在服务请求时,DispatcherServlet
循环遍历这些HandlerMapping
对象并测试它们中的每一个getHandler找到一个可以处理传入请求的方法,表示为标准HttpServletRequest
。从 4.3.x 开始,如果没有找到任何, it 记录警告你看到的
未找到 HTTP 请求与 URI 的映射[/some/path]
in DispatcherServlet
名称为 SomeName
and either抛出一个NoHandlerFoundException或者立即提交带有 404 Not Found 状态代码的响应。
为什么没有DispatcherServlet
find a HandlerMapping
可以处理我的请求吗?
最常见的HandlerMapping
实施是RequestMappingHandlerMapping,它处理注册@Controller
beans 作为处理程序(实际上是他们的@RequestMapping
带注释的方法)。您可以自己声明这种类型的 bean(使用@Bean
or <bean>
或其他机制)或者你可以使用内置选项。这些都是:
- 注释你的
@Configuration
与 一起上课@EnableWebMvc
.
- 声明一个
<mvc:annotation-driven />
XML 配置中的成员。
正如上面的链接所描述的,这两个都会注册一个RequestMappingHandlerMapping
豆(和一堆其他东西)。然而,一个HandlerMapping
如果没有处理程序,则不是很有用。RequestMappingHandlerMapping
期望一些@Controller
beans 所以你也需要声明它们,通过@Bean
Java 配置中的方法或<bean>
XML 配置中的声明或通过组件扫描@Controller
任一中带注释的类。确保这些豆子存在。
如果您收到警告消息和 404 并且您已正确配置上述所有内容,那么您将请求发送到了错误的 URI,一个未被检测到的处理@RequestMapping
带注释的处理程序方法。
The spring-webmvc
库提供其他内置HandlerMapping
实施。例如,BeanNameUrlHandlerMapping maps
从 URL 到名称以斜杠(“/”)开头的 beans
并且您可以随时编写自己的。明显地,您必须确保您发送的请求至少与注册的请求之一匹配HandlerMapping
对象的处理程序。
如果您没有隐式或显式注册任何HandlerMapping
豆类(或者如果detectAllHandlerMappings is true
), the DispatcherServlet
注册一些defaults。这些定义在DispatcherServlet.properties在同一个包中DispatcherServlet
班级。他们是BeanNameUrlHandlerMapping
and DefaultAnnotationHandlerMapping(这类似于RequestMappingHandlerMapping
但已弃用)。
调试
Spring MVC 将记录通过注册的处理程序RequestMappingHandlerMapping
。例如,一个@Controller
like
@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 匹配才能选择处理程序。
Other HandlerMapping
实现记录它们自己的语句,这些语句应该暗示它们的映射及其相应的处理程序。
同样,在 DEBUG 级别启用 Spring 日志记录以查看 Spring 注册了哪些 bean。它应该报告它找到了哪些带注释的类,它扫描了哪些包,以及它初始化了哪些bean。如果您期望的人不存在,请检查您的ApplicationContext
配置。
其他常见错误
A DispatcherServlet
只是一个典型的 Java EEServlet。你用你的典型注册它<web.xml>
<servlet-class>
and <servlet-mapping>
声明,或直接通过ServletContext#addServlet in a WebApplicationInitializer,或者使用 Spring boot 使用的任何机制。因此,您必须依赖网址映射中指定的逻辑Servlet 规范,请参阅第 12 章。另请参阅
- web.xml 中的 Servlet url 映射是如何使用的?
考虑到这一点,一个常见的错误是注册DispatcherServlet
url 映射为/*
,从 a 返回视图名称@RequestMapping
handler 方法,并期望呈现 JSP。例如,考虑像这样的处理程序方法
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
return "example-view-name";
}
with an InternalResourceViewResolver
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
您可能期望该请求是转发的到路径中的 JSP 资源/WEB-INF/jsps/example-view-name.jsp
。这不会发生。相反,假设上下文名称为Example
, the DisaptcherServlet
将报告
未找到 HTTP 请求与 URI 的映射[/Example/WEB-INF/jsps/example-view-name.jsp]
in DispatcherServlet
名为“调度员”
因为DispatcherServlet
被映射到/*
and /*
匹配所有内容(除了精确匹配,它具有更高的优先级),DispatcherServlet
将被选择来处理forward
来自JstlView(由返回InternalResourceViewResolver
). 几乎在所有情况下,DispatcherServlet
不会被配置为处理此类请求.
相反,在这种简单的情况下,您应该注册DispatcherServlet
to /
,将其标记为默认 servlet。默认 servlet 是请求的最后一个匹配项。这将允许您的典型 Servlet 容器选择一个内部 Servlet 实现,映射到*.jsp
,处理JSP资源(例如,Tomcat有JspServlet),然后再尝试使用默认 servlet。
这就是您在示例中看到的内容。