在详细介绍Spring MVC架构之前,让我们首先看看用于Web开发的两种流行的设计模式。
前控制器设计模式
此设计模式对所有传入请求强制执行单个入口点。所有请求都由单个代码处理,然后可以将处理请求的责任进一步委托给其他应用程序对象。
前控制器设计模式
MVC设计模式
这种设计模式通过将各种关注点分离到不同的层中来帮助我们开发松耦合应用程序。MVC设计模式将应用程序强制分为三层,即Model,View和Controller。
Model:代表应用程序数据。
View:这表示应用程序的用户界面。View将模型作为输入,并将其适当地呈现给最终用户。
Controller:控制器负责处理请求并生成模型,并为请求选择适当的视图。
Spring的MVC模块
Spring的MVC模块基于前端控制器设计模式,然后是MVC设计模式。所有传入的请求均由名为DispatcherServlet 的单个Servlet处理,该Servlet 充当Spring的MVC模块中的前端控制器。然后,DispatcherServlet 会引用 HandlerMapping 查找可以处理请求的控制器对象。然后,DispatcherServlet将请求分派到控制器对象,以便它实际上可以执行业务逻辑来满足用户请求。(控制器可以将责任委托给称为服务对象的其他应用程序对象)。控制器返回包含模型对象和视图对象(或视图的逻辑名称)的封装对象。在Spring的MVC中,此封装的对象由ModelAndView 类表示。如果ModelAndView 包含视图的逻辑名称,则 DispatcherServlet 引用ViewResolver 来基于逻辑名称查找实际的View对象。然后,DispatcherServlet 将模型对象传递给视图对象,然后将其呈现给最终用户。
2.DispatcherServlet
DispatcherServlet 在Spring的MVC模块中充当前端控制器。所有用户请求都由该servlet处理。由于这与其他任何Servlet一样,因此必须在应用程序的Web部署描述符文件即web.xml中进行配置。
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Library</display-name>
<servlet>
<servlet-name>myLibraryAppFrontController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myLibraryAppFrontController</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>welcome.htm</welcome-file>
</welcome-file-list>
</web-app>
我们已将该servlet命名为“ myLibraryAppFrontController ”。servlet映射部分中的URI模式是“ * .htm ”。因此,所有与URI模式匹配的请求都将由myLibraryAppFrontController 处理。
3. Spring应用程序上下文
- 默认应用程序上下文文件
- 用户定义的应用程序上下文文件
- 多个应用程序上下文文件
默认应用程序上下文文件
默认情况下,调度程序Servlet从名称为[servlet name] -servlet.xml的 XML文件中加载Spring应用程序上下文。因此,当我们的servlet myLibraryAppFrontController由容器加载时,它将从XML文件“ /WEB-INF/myLibraryAppFrontController-servlet.xml ” 加载Spring应用程序上下文。
用户定义的应用程序上下文文件
通过为调度程序servlet提供初始化参数,我们可以覆盖默认XML文件的名称和位置。初始化参数的名称为contextConfigLocation。参数值指定容器需要加载的应用程序上下文的名称和位置。
<servlet>
<servlet-name>myLibraryAppFrontController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:libraryAppContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
在上面的servlet配置中,我们提供了多个XML文件作为初始化参数值。所有这些XML文件将在初始化servlet myLibraryAppFrontController时由容器加载。
4. Spring Handler映射
- BeanNameUrlHandlerMapping
- SimpleUrlHandlerMapping
顾名思义,处理程序映射将请求与相应的请求处理程序(实际上是处理程序执行链)进行映射。当请求到达Spring的调度程序servlet时,它将请求移交给处理程序映射。然后,处理程序映射检查请求,并标识适当的处理程序执行链,并将其交付给调度程序servlet。处理程序执行链包含与传入请求匹配的处理程序,还可以选择包含应用于该请求的拦截器列表。然后,分派器Servlet执行处理程序和任何关联的处理程序拦截器。
Spring的MVC模块提供了许多处理程序映射的实现。其中一些描述如下。所有处理程序映射类都实现org.springframework.web.servlet.HandlerMapping 接口。
BeanNameUrlHandlerMapping
处理程序映射的此实现将传入请求的URL与控制器bean的名称进行匹配。然后,将匹配的Bean用作请求的控制器。这是Spring的MVC模块使用的默认处理程序映射,即,如果调度程序Servlet在Spring的应用程序上下文中找不到任何定义的处理程序映射bean,则调度程序servlet使用BeanNameUrlHandlerMapping。
让我们假设我们的应用程序中有三个网页。页面的URL为:
- http://服务器名称:端口号/ApplicationContext/welcome.htm
- http://服务器名称:端口号/ApplicationContext/listBooks.htm
- http://服务器名称:端口号/ApplicationContext/displayBookContent.htm
将执行业务逻辑以完成对以上页面做出的请求的控制器是:
- net.codejava.frameorks.spring.mvc.controller.WelcomeController
- net.codejava.frameorks.spring.mvc.controller.ListBooksController
- net.codejava.frameorks.spring.mvc.controller.DisplayBookTOCController
因此,我们需要在Spring的应用程序上下文文件中定义控制器,以使控制器的名称与请求的URL匹配。XML配置文件中的控制器bean如下所示。
<bean
name="/welcome.htm"
class="net.codejava.frameorks.spring.mvc.controller.WelcomeController" />
<bean
name="/listBooks.htm"
class="net.codejava.frameorks.spring.mvc.controller.ListBooksController"/>
<bean
name="/displayBookTOC.htm"
class="net.codejava.frameorks.spring.mvc.controller.DisplayBookTOCController"/>
注意,我们不需要在Spring的应用程序上下文文件中定义BeanNameUrlHandlerMapping,因为这是使用的默认值。
SimpleUrlHandlerMapping
该BeanNameUrlHandlerMapping时提出的限制控制器上的豆子,他们应该匹配传入请求的URL的名称。SimpleUrlHandlerMapping 消除了此限制,并使用属性“ mappings ” 将控制器bean映射为请求URL 。
<bean
id="myHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/welcome.htm">welcomeController</prop>
<prop key="/listBooks.htm">listBooksController</prop>
<prop key="/displayBookTOC.htm">displayBookTOCController</prop>
</props>
</property>
</bean>
<bean name="welcomeController"
class="net.codejava.frameorks.spring.mvc.controller.WelcomeController"/>
<bean name="listBooksController"
class="net.codejava.frameorks.spring.mvc.controller.ListBooksController"/>
<bean name="displayBookTOCController"
class="net.codejava.frameorks.spring.mvc.controller.DisplayBookTOCController"/>
<prop>元素的关键字是传入请求的URL模式。<prop>元素的值是控制器bean的名称,它将执行业务逻辑来满足请求。SimpleUrlHandlerMapping 是最常用的处理程序映射之一。
5. Spring Controllers
- MultiActionController
控制器是执行业务逻辑以满足传入请求的实际代码。控制器也可以将此责任委托给其他服务对象。所有用户定义的控制器都必须实现接口Controller或扩展抽象类AbstractController 。用户定义的控制器需要重写handleRequestInternal 方法。方法handleRequestInternal 以HttpServletRequest 和HTTPServletResponse 作为输入,并返回ModelAndView 的对象。
在Spring的应用程序上下文文件中,我们定义了一个用户定义的自定义控制器,名称为