Spring MVC 体系概述

Spring MVC 框架围绕 DispatcherServlet 这个核心展开,DispatcherServlet 是 Spring MVC 的总导演、总策划,它负责截获请求并将其分派给相应的处理器处理。Spring MVC 框架包括注解驱动控制器、请求及响应的信息处理、视图解析、本地化解析、上传文件解析、异常处理及表单标签绑定等内容。

1.体系结构

Spring MVC 是基于 Model 2 实现的技术框架,Model 2 是经典的MVC(Model、View、Control)模型在 Web 应用中的变体,这个改变主要源于 HTTP 协议的无状态性。Model 2 的目的和 MVC 一样,也是利用处理器分离模型、视图和控制,达到不同技术层级间松散层耦合的效果,提高系统灵活性、复用性和可维护性。在大多数情况下,可以将 Model 2 与 MVC 等同起来。

在利用 Model 2 之前,把所有的展现逻辑和业务逻辑集中在一起,有时也称这种应用模式为 Model 1。Model 1 的主要缺点就是紧耦合,复用性差,维护成本高。

由于 Spring MVC 是基于 Model 2 实现的框架,所以它底层的机制也是 MVC,通过下图描述 Spring MVC 的整体架构。

从接收请求到返回响应,Spring MVC 框架的众多组件通力配合、各司其职,有条不紊地完成分内的工作。在整个框架中,DispatcherServlet 处于核心的位置,它负责协调和组织不同组件以完成请求处理并返回响应的工作。和大多数 Web 框架一样,Spring MVC 通过一个前端 Serviet 接收所有的请求,并将具体工作委托给其他组件进行处理,DispatcherServlet 就是 Spring MVC 的前端 Servlet。下面对 Spring MVC 处理请求的整体过程进行讲解。

(1)整个过程始于客户端发出一个 HTTP 请求,Web 应用服务器接收到这个请求。如果匹配 DispatcherServlet 的请求映射路径(在 web.xml 中指定),则 Web 容器将该请求转交给 DispatcherServlet 处理。

(2)DispatcherServlet 接收到这个请求后,将根据请求的信息(包括URL、HTTP方法、请求报文头、请求参数、Cookie等)及 HandlerMapping 的配置找到处理请求的处理器(Handler)。可将看作路由控制器,将 Handler 看作目标主机。值得注意的是,在 Spring MVC 中并没有定义一个 Handler 接口,实际上,任何一个 Object 都可以成为请求处理器。

(3)当 DispatcherServlet 根据 HandlerMapping 得到对应当前请求的 Handler 后,通过 HandlerAdapter 对 Handler 进行封装,再以统一的适配器接口调用 Handler。HandlerAdapter 是 Spring MVC 的框架级接口,顾名思义,HandlerAdapter 是一个适配器,它用统一的接口对各种 Handler 方法进行调用。

(4)处理器完成业务逻辑的处理后将返回一个 ModelAndView 给 DispatcherServlet,ModelAndView 包含了视图逻辑名和模型数据信息。

(5)ModelAndView 中包含的是“逻辑视图名”而非真正的视图对象,DispatcherServlet 借由 ViewResolver 完成逻辑视图名到真实视图对象的解析工作。

(6)当得到真实的视图对象 View 后,DispatcherServlet 就使用这个 View 对象对 ModelAndView 中的模型数据进行视图渲染。

(7)最终客户端得到的响应消息可能是一个普通的 HTML 页面,也可能是一个 XML 或 JSON 串,甚至是一张图片或一个 PDF 文档等不同的媒体形式。

以上每个步骤都包含丰富的知识点,本章将逐步揭示每个组件的“庐山真面目”。不过现在请收好所有的好奇心,我们第一步要做的是在 web.xml 中配置好 DispatcherServlet,让 Spring MVC 的“心脏”跳动起来。

2.配置DispatcherServIet

DispatcherServlet 是 Spring MVC 的“灵魂”和“心脏”,它负责接收 HTTP 请求并协调 Spring MVC 的各个组件完成请求处理的工作。和任何 Servlet 一样,用户必须在 web.xml 中配置好 DispatcherServlet。

要了解 Spring MVC 框架的工作机理,必须回答以下3个问题。

(1)DispatcherServlet 框架如何截获特定的 HTTP 请求并交由 Spring MVC 框架处理?

(2)位于 Web 层的 Spring 容器(WebApplicationContext)如何与位于业务层的 Spring 容器(ApplicationContext)建立关联,以使 Web 层的 Bean 可以调用业务层的 Bean?

(3)如何初始化 Spring MVC 的各个组件,并将它们装配到 DispatcherServlet 中?

1)配置 DispatcherServlet,截获特定的URL请求

大家知道,我们可以在 web.xml 中配置一个 Servlet,并通过 <servlet-mapprng> 指定其处理的URL。这是传统的 DispatcherServlet 配置方式。而 Spring4.0 已经全面支持 Servlet 3.0,因此也可以采用编程式的配置方式。这里先采用传统的 web.xml 的方式进行讲解,然后介绍基于 Servlet 3.0 的新方式。假设我们希望 Spring MVC 的 DispatcherServlet 能截获并处理所有以 .html 结束的 URL 请求,那么可以在 web.xml 中按如下方式进行配置,如下面代码所示。

<!-- ①业务层和持久层的Spring配置文件,这些配置文件被父Spring容器所使用 --><context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:/applicationContext.xml</param-value>
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- ②声明DispatcherServlet -->
<servlet>
  <servlet-name>smart</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>
<!-- ③名为DispatcherServlet匹配的URL模式 -->
<servlet-mapping>
  <servlet-name>smart</servlet-name>
  <url-pattern>.html</url-pattern>
</servlet-mapping>

在①处,通过 contextConfigLocation 参数指定业务层 Spring 容器的配置文件(多个配置文件使用逗号分隔)。ContextLoaderListener 是一个ServletContextListener,它通过 contextConfigLocation 参数所指定的 Spring 配置文件启动“业务层”的 Spring 容器。

在②处配置了名为 smart 的 DispatcherServlet,它默认自动加载 /WEB-INF/smart-servlet.xml(<servlet-Name>-servlet.xml)的 Spring 配置文件,启动 Web 层的 Spring 容器。

在③处,通过 <servlet-mappmg> 指定 DispatcherServlet 处理所有以 .html 为后缀的 HTTP 请求,即所有带 .html 后缀的 HTTP 请求都会被 DispatcherServlet 截获并处理。

我们知道,多个 Spring 容器之间可设置为父子级的关系,以实现良好的解耦。在这里,"web层” Spring容器将作为“业务层” Spring 容器的子容器,即“web层”容器可以引用“业务层”容器的 Bean,而“业务层”容器却访问不到"web层”容器的Bean。

需要提醒的是,一个 web.xml 可以配置多个 DispatcherServlet,通过其 <servlet-mapping> 配置,让每个 DispatcherServlet 处理不同的请求。

DispatcherServlet 遵循“契约优于配置”的原则,在大多数情况下,用户无须进行额外的配置,只需按契约行事即可。

如果确实要对 DispatcherServlet 的默认规则进行调整,则 Dispatcherservlet 是“敞开胸怀”的。下面是常用的一些配置参数,可通过 <servlet> 的 <init-param>  指定。

(1)namespace:DispatcherServlet 对应的命名空间,默认为 <servlet-name>-servlet,用于构造 Spring 配置文件的路径。在显式指定该属性后,配置文件对应的路径为 WEB-INF/<namespace>.xml,而非 WEB-INF/<servlet-name>-servlet.xml。如果将 namespace 设置为 sample,则对应的 Spring 配置文件为 WEB-INF/sample.xml

(2)contextConfigLocation:如果 DispatcherServlet 上下文对应的 Sprlng 配置文件有多个,则可以使用该属性按照 Spring 资源路径的方式指定。如“classpath:samplel.xml,classpath:sample2.xml”,DispatcherServIet 将使用类路径下的 samplel.xml 和 sample2.xml 这两个配置文件初始化 WebApplicationContext。

(3)publishContext:布尔类型的属性,默认值为 ture。DispatcherServlet 根据该属性决定是否将 WebApplicationContext 发布到 ServletContext 的属性列表中,以便调用者可借由 ServletContext 找到 WebApplicationContext 实例,对应的属性名为 DispatcherServlet#getServletContextAttributeName() 方法的返回值。

(4)publishEvents:布尔类型的属性。当 DispatcherServlet 处理完一个请求后,是否需要向容器发布一个 ServletRequestHandledEvent 事件,默认值为 true。如果容器中没有任何事件监听器,则可以将该属性设置为 false,以便提高运行性能。

下面的代码显式指定 web 层的 Spring 配置文件。

<servlet>
  <servlet-name>smart</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/webApplicationContext.xml</param-value>
    </init-param>
</servlet>

之前提到 Spring4.0 已全面支持 Servlet3.0,因此,在3.0环境中,也可以使用编程的方式来配置 Servlet 容器。下面的代码可达到和上面代码同样的效果。

public class SmartApplicationInitializer implements WebApplicationInitializer《
    @Override
    public void onStartup(ServletContext container){
        ServietRegistration.Dynamic registration = container.addServlet("dispatcher",new
            DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping(".html");
    }
}

接下来看看 Servlet3.0 的实现原理。在 Servlet3.0 环境中,容器会在类路径中查找实现 javax.servlet.ServletContainerInitializer 的类,如果发现已有实现类,就会调用它来配置 Servlet 容器。在 Spring 中,org.springframework.web.SpringServletContainerInitializer 类实现了该接口,同时这个类又会查找实现org.springframework.web.WebApplicationInitializer 接口的类,并将配置任务交给这些实现类去完成。另外, Spring 提供了一个便利的抽象类 AbstractAnnotationConfigDispatcherServletlnitializer 来实现这个接口,使得它在注册 DispatcherServlet 时只需简单地指定它的 Serviet 映射即可。在上述示例中,当应用部署到 3.0 容器中时,容器启动时会自动发现它,并使用它来配置 Servlet 上下文。

2)探究 DispatcherServIet 的内部逻辑

现在剩下的最后一个问题是:Spring 如何将上下文中的 Spring MVC 组件装配到 DispatcherServIet 中?通过查看DispatcherServlet 的 initStrategies() 方法的代码,一切真相就大白于天下了。

protected void initStrategies(ApplicationContext context){
    initMultipartResolver();//①初始化上传文件解析器(直译为多部分请求解析器)
    initLocaleResolver();//②初始化本地化解析器
    initThemeResolver();//③初始化主题解析器
    initHandlerMappings();//④初始化处理器映射器
    initHandlerAdapters();//⑤初始化处理器适配器
    initHandIerExceptionResolver();//⑥初始化处理器异常解析器
    initRequestToViewNameTranslator();//⑦初始化请求到视图名翻译器
    initViewResolvers();//⑧初始化视图解析器
}

initStrategies() 方法将在 WebApplicationContext 初始化后自动执行,此时 Spring 上下文中的 Bean 已经初始化完毕。该方法的工作原理是:通过反射机制查找并装配 Spring 容器中用户显式自定义的组件 Bean,如果找不到,则装配默认的组件实例。

Spring MVC 定义了一套默认的组件实现类,也就是说,即使在 Spring 容器中没有显式定义组件 Bean,DispatcherServlet 也会装配好一套可用的默认组件。在 spring-webmvc-4.x.jar 包的 org/springframework/web/servlet 类路径下拥有一个 DispatcherServlet.properties 配置文件,该文件指定了 DispatcherServlet 所使用的默认组件。

##本地化解析器
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

##主题解析器
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

##处理器映射(共2个)
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

##处理器适配器(共3个)
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

##异常处理器(共3个)
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

##视图名称翻译器
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

##视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

有些组件最多允许存在一个实例,如 MultipartResolver、LocaleResolver 等,而另一些组件允许存在多个实例,如 HandlerMappmg、HandlerAdapter 等。同一类型的组件如果存在多个,那么它们之间的优先级顺序如何确定呢?这些组件都实现了 org.springframework.core.Ordered接口,可通过 order 属性确定优先级顺序,值越小优先级越高。

简言之,当 DispatcherServlet 初始化后,就会自动扫描上下文的 Bean,根据名称或类型匹配的机制查找自定义的组件,找不到时则使用 DispatcherServlet.properties 定义的默认组件

原文地址:https://www.cnblogs.com/jwen1994/p/11111769.html

时间: 2024-08-01 06:14:21

Spring MVC 体系概述的相关文章

Spring MVC 设计概述

MVC设计的根本原因在于解耦各个模块 Spring MVC的架构 对于持久层而言,随着软件发展,迁移数据库的可能性很小,所以在大部分情况下都用不到Hibernate的HQL来满足移植数据库的要求.与此同时,性能对互联网更为重要,不可优化SQL.不够灵活成了Hibernate难以治愈的伤痛,这样MyBatis就崛起了.无论是Hibernate还是MyBatis都没处理好数据库事务的编程,同时随着各种NoSQL的强势崛起,使得Java Web应用不仅能够在数据库获取数据,也可以从NoSQL中获取数据

Spring MVC 编程基础

p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; font-size: 12.0pt; font-family: Consolas } h1 { margin-top: 17.0pt; margin-right: 0cm; margin-bottom: 16.5pt; margin-left: 21.25pt; text-align: justify

带着问题学 Spring MVC 源码: 一、概述

摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! 简单就好,生活可以很德国 Q:什么是 Spring MVC ? ※ Spring MVC 是 Spring Web 的一个重要模块.Spring 支持 Web 应用,Spring MVC 是对 MVC 模式的支持. Q:MVC 模式? ※ MVC 模式是种经典的软件架构,分 Model 模型.View 视图及 Controller 控制器 三种角色.架构的意图明显区分三种角色的职责,使其不相互

01 - spring mvc 概述及配置DispatcherServlet

1.Spring mvc 基于model2实现,整体框架流程如(图片来自百度): ①web容器接收到http请求,若匹配DispatcherServlet的请求映射路径(web.xml),则容器会交给DispatcherServlet处理. ②DispatcherServlet根据请求的信息及handlerMapping(类似路由功能)的配置找到处理请求的Handler. ③Handler adapter对handler进行封装,使用统一的方法对Handler方法进行调用 ④处理器完成业务逻辑后

spring MVC概述

springMVC是当前最优秀的MVC框架,springMVC使用简单,学习成本低,很容易写出性能优秀的程序,灵活性高. 1.Spring MVC的核心类与接口 DispatcherServlet  前段控制器(总控制器),将发送的请求转发到具体控制类. HandlerMapping  映射处理器,负责映射中央处理器转发给Controller时的映射策略.一共分为三种. 1.BeanNameUrlHanderMapping: 按着controller的name来映射寻找.默认 2.SimpleU

Spring MVC 概述

[简介] Spring MVC也叫Spring web mvc,属于表现层的框架.SpringMVC是Spring框架的一部分,是在Spring 3.0后发布的. 由以上Spring的结构图可以看出,Spring由四大部分组成:Dao部分(DAO与ORM).AOP部分.Web部分(JEE与Web)及IOC容器部分(Core). 原文地址:https://www.cnblogs.com/zhzcode/p/9606964.html

Maven+Hibernate+Spring+Spring MVC开发新闻发布系统

使用Maven+Hibernate+Spring+Spring MVC开发新闻发布系统 课程学习地址:http://www.xuetuwuyou.com/course/163 课程出自学途无忧网:http://www.xuetuwuyou.com 课程介绍 一.课程用到的软件: 1.jdk 1.8 2.eclipse neon 3.tomcat 8 4.jetty 5.MySQL  6.navicat 9+ 二.课程涉及到的技术点 1.Maven基础 2.Maven高级 3.Hibernate

Spring MVC 简述:从MVC框架普遍关注的问题说起

任何一个完备的MVC框架都需要解决Web开发过程中的一些共性的问题,比如请求的收集与分发.数据前后台流转与转换,当前最流行的SpringMVC和Struts2也不例外.本文首先概述MVC模式的分层思想与MVC框架普遍关注的问题,并以此为契机结合SpringMVC的入门级案例简要地从原理.架构角度介绍了它对这些问题的处理,包括请求处理流程.消息转换机制和数据绑定机制等核心问题.最后,本文对目前最为流行的两个MVC框架SpringMVC 和 一. MVC 模式与框架 1.MVC 模式 Java We

【Spring】Spring MVC原理及配置详解

1.Spring MVC概述: Spring MVC是Spring提供的一个强大而灵活的web框架.借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单.这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其他bean,通过Spring的依赖注入功能,这些bean被注入到控制器中. Spring MVC主要由DispatcherServlet.处理器映射.处理器(控制器).视图解析器.视图组成.他的两个核心是两个核心: 处理器映射:选择使用