DispatcherServlet,Resolver和Controllers如何交互?

时间:2012-12-23 23:49:49

标签: spring jsp spring-mvc

好的,所以我遇到了相当常见的错误:

WARNING: No mapping found for HTTP request with URI [/WEB-INF/jsp/index.jsp] in DispatcherServlet with name 'app'

我正在查看现有的答案,我没有看到组件如何相互作用的真正好的解释。鉴于我无法根据现有答案解决我的问题,我希望有人能够详细解释DispatcherServletResolver的功能。

在Eclipse中开发,我有以下结构:

/src/com/whiuk/philip/web/controller/IndexController.java
/WebContent
/WebContent/WEB-INF
/WebContent/WEB-INF/web.xml
/WebContent/WEB-INF/app-servlet.xml
/WebContent/WEB-INF/jsp/index.jsp

Eclipse Deployment Assembly意味着它部署如下:

/src -> WEB-INF/classes
/WebContent -> /
/ivy.xml[*] -> WEB-INF/lib

我有一个 web.xml 文件,用于定义DispatcherServlet和所有文件的映射(/*

<servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

我有一个 app-servlet.xml 文件,用于扫描包并定义InternalResourceViewResolver

<context:component-scan base-package="com.whiuk.philip.web" />
<mvc:annotation-driven />
<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

我有一个IndexController,它有索引的RequestMapping:

 @Controller
 public class IndexController {
      @RequestMapping(value = "/index", method = RequestMethod.GET)
      public ModelAndView index() {
             return new ModelAndView();
      }
 }

日志显示已注册:

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
INFO: Mapped "{[/index],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}"
onto public org.springframework.web.servlet.ModelAndView 
com.whiuk.philip.web.controller.IndexController.index()

最后我有一个 index.jsp 文件。

有人可以解释导致错误配置的原因导致顶部显示的错误,如果可能的话,还会提供一个关于DispatcherServlet,解析器以及它们如何输入控制器的目的的句子。

2 个答案:

答案 0 :(得分:47)

我将尝试在Spring Web MVC应用程序中解释请求的“流程”。

向您的应用程序发送请求时,会发生以下情况:

  • 请求到达您的服务器(例如Tomcat)。根据URL中的上下文路径,服务器决定请求所属的应用程序。
  • 根据应用程序的web.xml文件中的url和servlet映射,服务器知道哪个servlet应该处理请求。
  • 请求被传递到servlet filter链,可以修改或拒绝请求
  • servlet控制请求。如果是Spring应用程序,则Spring Dispatcherservlet会收到请求。现在春天开始了
  • 请求由mvc intercepters preHandle种方法
  • 处理
  • 请求根据网址映射到控制器。将调用相应的控制器方法。
  • 您的控制器正在处理请求。可以在控制器中返回许多不同的响应(jsp,pdf,json,重定向等)。现在我假设你想渲染一个简单的jsp视图。控制器的结果有两个:模型和视图。该模型是一个地图,其中包含您稍后要在视图中访问的数据。此阶段的视图大多数情况下是包含视图名称的简单字符串。
  • 已注册的弹簧mvc拦截器可以使用postHandle方法重新启动(例如修改模型)
  • 使用ViewResolver将控制器的“查看”结果解析为真实视图。根据ViewResolver,结果可以是jsp页面,tiles viewthymeleaf template或许多其他“视图”。在您的情况下,ViewResolver会将视图名称(例如“myPage”)解析为jsp文件(例如/WEB-INF/jsp/myPage.jsp
  • 使用控制器返回的模型数据呈现视图
  • 渲染视图的响应将再次传递给mvc拦截器(afterCompletion方法)
  • 响应离开调度程序servlet。这里结束了春天的土地。
  • 响应再次传递servlet过滤器
  • 将回复发送回客户

如果我不是100%正确或者我错过了某些东西,请随意纠正我: - )

答案 1 :(得分:8)

基本上发生的事情是,因为Spring的DispatcherServlet映射到/*,它往往会被调用每个请求(这没关系),但不幸的是,即使请求被分派到JSP页面也会被调用(/WEB-INF/jsp/index.jsp),而不是调用容器默认servlet。

我所知道的修复方法如下:

将其映射到默认的servlet路径/,而不是:

<servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

您将在上面看到的一个问题是,不幸的是,您的webapp根目录下的资源将由DispatcherServlet处理,而DispatcherServlet将不知道该怎么做,修复程序是register a default-servlet-handler this way

<mvc:default-servlet-handler />