为什么Spring MVC用404响应,并报告“在DispatcherServlet中没有find具有URI的HTTP请求的映射”?
我正在编写一个部署在Tomcat上的Spring MVC应用程序。 请参阅以下最小,完整且可validation的示例 :
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.example.controllers有一个@Controller
@Controller public class ExampleController { @RequestMapping(path = "/home", method = RequestMethod.GET) public String example() { return "index"; } }
我的应用程序的上下文名称是Example 。 当我发送请求到
http://localhost:8080/Example/home
应用程序响应一个HTTP状态404并logging下列内容
WARN osweb.servlet.PageNotFound - No mapping found for HTTP request with URI `[/Example/WEB-INF/jsps/index.jsp]` in `DispatcherServlet` with name 'dispatcher'
我有一个JSP资源在/WEB-INF/jsps/index.jsp我期望Spring MVC使用我的控制器来处理请求并转发到JSP,那么为什么它响应404?
这是一个关于这个警告信息的问题的标准post。
您的标准Spring MVC应用程序将通过您在Servlet容器中注册的DispatcherServlet来处理所有请求。
DispatcherServlet查看它的ApplicationContext ,如果可用的话,查看ApplicationContext注册到一个ContextLoaderListener的特殊bean,它需要设置它的请求服务逻辑。 这些bean在文档中描述 。
可以说是最重要的,types为HandlerMapping bean的映射
传入的处理程序请求以及基于某些标准的处理前后处理程序(处理程序拦截程序)列表,其中的细节因
HandlerMapping实现而异。 最stream行的实现支持带注释的控制器,但也存在其他实现。
HandlerMapping的javadoc进一步描述了实现的行为。
DispatcherServlet查找所有这种types的bean,并以某种顺序注册它们(可以自定义)。 在提供请求时, DispatcherServlet遍历这些HandlerMapping对象,并使用getHandlertesting每个对象,以find可处理传入请求的对象,并将其表示为标准的HttpServletRequest 。 从4.3.x开始, 如果没有find ,它会logging你看到的警告
在名为SomeName的
DispatcherServlet找不到具有URI[/some/path]HTTP请求的映射
并引发NoHandlerFoundException或立即提交404 Not Found状态代码的响应。
为什么DispatcherServlet找不到可以处理我的请求的HandlerMapping ?
最常见的HandlerMapping实现是RequestMappingHandlerMapping ,它处理注册@Controller bean作为处理程序(的确是它们的@RequestMapping注释方法)。 您可以自己(使用@Bean或<bean>或其他机制)声明此types的bean,也可以使用内置选项 。 这些是:
- 使用
@EnableWebMvc注释您的@Configuration类。 - 在XMLconfiguration中声明一个
<mvc:annotation-driven />成员。
正如上面的链接所描述的,这两个都会注册一个RequestMappingHandlerMapping bean(以及其他一些东西)。 但是,如果没有处理程序, HandlerMapping不是很有用。 RequestMappingHandlerMapping需要一些@Controller bean,所以你也需要通过Javaconfiguration中的@Bean方法或者XMLconfiguration中的<bean>声明或者通过@Controller注释类的组件扫描来声明这些<bean> 。 确保这些豆存在。
如果您收到警告消息和404,并且已经正确configuration了上述所有内容, 那么您将请求发送给错误的URI ,而不是由检测到的@RequestMapping注释处理程序方法处理。
spring-webmvc库提供了其他内置的HandlerMapping实现。 例如, BeanNameUrlHandlerMapping映射
从URL到名称以斜杠(“/”)开头的bean
而且你总是可以自己写。 显然, 你必须确保你发送的请求至less匹配一个注册的HandlerMapping对象的处理程序。
如果您没有显式注册任何HandlerMapping bean(或者detectAllHandlerMappings为true ),则DispatcherServlet注册一些默认值 。 这些在与DispatcherServlet类相同的包中的DispatcherServlet中定义。 它们是BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping (与RequestMappingHandlerMapping类似,但不赞成使用)。
debugging
Spring MVC将logging通过RequestMappingHandlerMapping注册的处理程序。 例如,一个@Controller像
@Controller public class ExampleController { @RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom") public String example() { return "example-view-name"; } }
将在INFO级别logging以下内容
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
这描述了注册的映射。 当看到没有find处理程序的警告时,将消息中的URI与此处列出的映射进行比较。 所有在@RequestMapping指定的限制都必须匹配Spring MVC来select处理程序。
其他HandlerMapping实现logging他们自己的语句,这些语句应该暗示它们的映射及其相应的处理程序。
同样,在DEBUG级别启用Spring日志logging来查看Spring注册的bean。 它应该报告find哪些注释类,它扫描哪个包,以及它初始化哪些bean。 如果你所期望的不存在,那么检查你的ApplicationContextconfiguration。
其他常见的错误
DispatcherServlet只是一个典型的Java EE Servlet 。 您可以使用典型的<web.xml> <servlet-class>和<servlet-mapping>声明,或直接通过WebApplicationInitializer ServletContext#addServlet ,或者使用Spring启动使用的任何机制。 因此,您必须依靠Servlet规范中指定的url映射逻辑,参见第12章。另请参见
- 如何使用web.xml中的Servlet URL映射?
考虑到这一点,一个常见的错误是将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; }
您可能希望将请求转发到path为/WEB-INF/jsps/example-view-name.jsp的JSP资源。 这不会发生。 相反,假设一个上下文名称为Example ,那么DisaptcherServlet将会报告
在名为“dispatcher”的
DispatcherServlet找不到具有URI的HTTP请求的映射[/Example/WEB-INF/jsps/example-view-name.jsp]
由于DispatcherServlet映射到/*和/*匹配所有内容(除了具有更高优先级的精确匹配外),因此将selectDispatcherServlet来处理由JstlView (由InternalResourceViewResolver返回)的forward 。 几乎在任何情况下, DispatcherServlet都不会被configuration为处理这样的请求 。
相反,在这个简单的情况下,你应该注册DispatcherServlet到/ ,标记为默认的servlet。 默认的servlet是请求的最后一个匹配项。 这将允许典型的servlet容器在尝试使用默认的servlet之前,select映射到*.jsp的内部Servlet实现来处理JSP资源(例如,Tomcat具有JspServlet )。
这就是你所看到的例子。
除了之前描述的,我解决了我的问题:`
@Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; }
added tomcat-embed-jasper:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency>
来自: JSP文件不在Spring Boot web应用程序中呈现
我遇到了同样错误的另一个原因。 这也可能是由于您的controller.java文件没有生成类文件。 由此,web.xml中提到的调度程序servlet无法将其映射到控制器类中的相应方法。
@Controller Class Controller{ @RequestMapping(value="/abc.html")//abc is the requesting page public void method() {.....} }
在Eclipse下的Project-> select clean – > Build Project.Do检查是否生成了在你的工作空间下构build的控制器文件的类文件。