您的标准Spring MVC应用程序将通过您在Servlet容器中注册的DispatcherServlet提供所有请求.
DispatcherServlet查看其ApplicationContext,如果可用,则使用ContextLoaderListener注册的ApplicationContext用于设置其请求服务逻辑的特殊bean. These beans are described in the documentation.
incoming requests to handlers and a list of pre- and post-processors
(handler interceptors) based on some criteria the details of which
vary by HandlerMapping implementation. The most popular implementation
supports annotated controllers but other implementations exists as
well.
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.这些是:
>使用@EnableWebMvc注释您的@Configuration类.
>声明一个< mvc:annotation-driven /> XML配置中的成员.
正如上面的链接所描述的,这两个都将注册一个RequestMappingHandlerMapping bean(以及一堆其他的东西).但是,没有处理程序,HandlerMapping不是很有用. RequestMappingHandlerMapping需要一些@Controller bean,所以你需要通过Java配置中的@Bean方法或< bean>来声明它们. XML配置中的声明或通过@Controller注释类的组件扫描.确保这些豆子存在.
如果您收到警告消息和404,并且您已正确配置了上述所有内容,则您将请求发送到错误的URI,该URI不会被检测到的@RequestMapping带注释的处理程序方法处理.
spring-webmvc库提供了其他内置的HandlerMapping实现.例如,BeanNameUrlHandlerMapping地图
from URLs to beans with names that start with a slash (“/”)
而你总是可以自己写.显然,您必须确保您发送的请求至少匹配一个已注册的HandlerMapping对象的处理程序.
如果您没有隐式或显式注册任何HandlerMapping bean(或者如果detectAllHandlerMappings为真),则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的类>和< servlet-mapping>声明,或直接通过WebApplicationInitializer中的ServletContext#addServlet,或Spring引导使用的任何机制.因此,您必须依赖于Servlet specification中指定的url映射逻辑,请参阅第12章.另请参阅
考虑到这一点,一个常见的错误是使用/ *的url映射注册DispatcherServlet,从@RequestMapping处理程序方法返回视图名称,并期望呈现JSP.例如,考虑一个像这样的处理程序方法
@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;
}
您可能希望请求是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来处理JstlView中的转发(由InternalResourceViewResolver返回).几乎在所有情况下,DispatcherServlet都不会配置为处理这样??的请求.
相反,在这种简单的情况下,您应该将DispatcherServlet注册到/,将其标记为默认servlet.默认servlet是请求的最后一个匹配项.这将允许您的典型servlet容器在尝试使用默认servlet之前选择映射到* .jsp的内部Servlet实现来处理JSP资源(例如,Tomcat具有JspServlet).
这就是你在你的例子中看到的.