Spring(二):SpringMvc详解

BEGIN

看过上一篇关于Spring框架的介绍后(点击查看Spring介绍),相信对于Spring已经有了整体的认知,接下来的文章我会对他的主要家族成员逐一做些介绍。

本文介绍的对象是–SpringMvc,仔细回想下这个框架的组成,不难发现它有专门的一块内容是来整合Web组件(右上角),它就在这里面,让我们来一起看下吧。

1、MVC

老生常谈的一个东西了,它的出现就摒弃原来一个jsp页面搞定所有事(UI、业务逻辑、数据交互等)的状况,做到各个层级分工协作,各司其职。View层处理前端UI展示,Model层用来处理业务逻辑,Control层则是用来协调和调度M和V,使得用户界面和业务处理分开,让我们的编码更加灵活、代码/模块的复用性也大大的提高、同时降低耦合提升整体应用程序的可维护性。

SpringMvc就是基于Mvc的一套前端web框架,他具有MVC的特征又得益于Spring的加持,所以它注定是一个优秀的框架。

在这里插入图片描述
如上图,是整个SpringMVC的一个模式总览,这里面占C位的就是我们的DispatcherServlet,负责来协调和调用不同组件进行工作,从而响应前端的请求。M位的由我们的后端控制器承担,处理业务/事务,V通过ViewResolver来定位解析视图。

讲到MVC一定会联想到struct2,struct2同样作为一个历史悠久的MVC框架,又有像SSH等框架的实际应用,它的地位不言而喻。那么它和SpringMVC有什么区别呢?

  • 基于的对象不一样。struts2是类级别开发的,一个类对应一个request上下文,而SpringMvc是基于方法级别的,一个方法对应一个request上下文。
  • 由于Spring的“零”配置特性,SpringMvc只要少量的配置
  • SpringMvc的效率会稍优

2、核心组件

在这里插入图片描述
DispatcherServlet
作用:框架的核心,前端控制器负责接收和响应用户的请求以及协调各个模块组件,降低组件之间的耦合度
配置:web.xml中配置,在系统启动时进行加载
HandlerMapping
作用:根据用户访问或请求的 URL去查找的Handler对象
实现:在spring-mvc.xml中进行配置
方式:框架提供多种的映射处理器来实现不同的映射:XML配置(配置繁杂)、实现接口、注解等
HandlerExecutionChain
作用:Handler执行链象,包括 Handler对象、拦截器等,用来处理和拦截相应的内容。
实现:无需配置,DispatcherServlet中会进行获取和遍历。如需拦截器进行相应拦截器的配置即可
HandlerAdapter
作用:让固定的Servlet来进行灵活的Handler的调用。就是将二者进行适配
实现:在spring-mvc.xml中进行配置
Handler
作用:主要是负责处理用户请求,当然其中还包括了像数据持久化的操作等等
实现:就是我们平常编写的Controller类
方式:最常用的方法就是添加@Controller的注解
ModelAndView、View
作用:逻辑视图和具体的实体对象,前者携带逻辑视图名,后者为具体的视图对象,前者通过渲染将逻辑参数填充到模板中,生成View再响应给用户
实现:View可以是jsp、pdf、freemarker、excel对象等等
ViewResolver
作用:进行视图解析,将逻辑视图名解析到具体的View
实现:在spring-mvc.xml中进行配置

3、核心流程

在这里插入图片描述
如上图,让我们来分析下整个的请求与响应流程

1、终端用户发起请求(浏览网站、请求数据等),请求会由核心控制器(DispatchServlet)接受
2、核心控制器(DispatchServlet)会调用处理器映射器(HandlerMapping)进行Url映射
3、处理器映射器(HandlerMapping)找出相应的处理执行链(HandlerExecutionChain)返回给控制器(DispatchServlet),链中包含有具体处理器、拦截器等
4、核心控制器(DispatchServlet)继续调用处理器适配器(HandlerAdapter)
5、处理器适配器(HandlerAdapter)进行处理器的适配后调用具体的处理器(Handler/Controller)
6、处理器(Handler、Controller)执行完后会返回模型视图(ModelAndView)对象给到适配器
7、处理器适配器(HandlerAdapter)将模型视图(ModelAndView)进一步传递返回给核心控制器(DispatchServlet)
8、核心控制器(DispatchServlet)将模型视图(ModelAndView)交给视图解析器(ViewResolver)请求进一步的解析
9、视图解析器(ViewReslover)解析后返回具体视图(View)给核心控制器(DispatchServlet)
10、核心控制器再对视图(View)进行进一步的渲染,将模型数据填充到页面或模板中,得到最终的视图对象
11、渲染后的视图(View)会响应给终端的用户完成整个的请求过程

上面这个整套的流程相信大家都应该看过不止一遍,因为毕竟我也是站在这么多巨人的肩膀上而进行文章的编写,所以不管是哪里的博文,只要是涉及到SpringMvc的原理都会有类似的图呈现出来, 而接下来我们再来看看他的部分核心源码以加深理解吧。

4、核心源码

既然占着C位的是DispatchServlet那么,我们就来简单地分析下它的源码吧
在这里插入图片描述
显然作为起源来说它来自HttpServlet,中间的两层HttpServletBean和FrameworkServlet是针对Servlet的基础上做了一些的初始化的操作。
HttpServletBean中通过init()初始化一些init-param标签中配置的参数
FrameworkServlet中通过initServletBean()初始化上下文的内容

再到DispatchServlet,首先它也会进行初始化的操作如下图所示,当触发刷新时将会执行以下初始化的工作
在这里插入图片描述
除了这些组件外它还会进行像:配置文件、扫描并实例化Bean到IoC容器中等等。

初始化完成应用程序启动后,当Servlet接收到请求后那么首先肯定会调用到我们的doGet或doPost方法了,这两个方法在FrameworkServlet中会将具体的逻辑交由doService来进行处理,如下图:
在这里插入图片描述
doService的方法在DispatchServlet中又得到了进一步的重写进而调用doDispatch方法
在这里插入图片描述
那么重点来了,doDispatch 就是我们要特别关注的重点,整个的SpringMvc的任务分发都是在这边完成的,如下图:
在这里插入图片描述
核心的三步曲已经被我框出来了,HandlerExecutionChain的获取以及通过适配器进行逻辑视图对象的获取,再到最后的视图的解析构成这幅艺术家的画卷

有兴趣了解各个方法内部实现的可以到相应的方法内部进行查看!

5、关键配置

我贴出一些我平时用到的关于Spring的关键配置,一个是方便自己后续索引,再来就是为广大的Developer分享。

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
       <display-name>smvc</display-name>
    <listener>
		<description>spring日志监听器</description>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <listener>
        <description>spring监听器</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <description>request监听器</description>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <listener>
        <description>系统初始化监听器</description>
        <listener-class>org.jeecgframework.web.system.listener.InitListener</listener-class>
    </listener>
       <!-- 核心控制器 -->
    <servlet>
        <description>spring mvc servlet</description>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <description>spring mvc 配置文件</description>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
    <!-- restUrl风格配置 -->
    <servlet>
        <servlet-name>restSpringMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <description>spring mvc 配置文件</description>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>restSpringMvc</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

spring-mvc.xml的部分配置:

<!-- 自动扫描controller包下的所有类 -->
    <context:component-scan base-package="com.*.*">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>
    <!-- IE执行AJAX时配置 -->
    <bean id="mappingJacksonHttpMessageConverter"
        class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
                <value>text/json;charset=UTF-8</value>
			    <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>
    <!-- 注册RequestMappingHandlerMapping -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    <!-- 默认的视图解析器- -->
    <bean id="defaultViewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:order="3">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="contentType" value="text/html" />
        <property name="prefix" value="/webpage/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
        p:defaultEncoding="UTF-8">
        <property name="maxUploadSize">
            <value>104857600</value>
        </property>
        <property name="maxInMemorySize">
            <value>4096</value>
        </property>
    </bean>
<!-- Bean解析器 -->
<bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0" />

6、常用注解

  • @Controller 控制器类
  • @RequestMapping 指定URL请求的路径,以供映射器检索
  • @RequestBody 读取Request请求的body部分数据
  • @ResponseBody 写入到Response对象的body数据区
  • @ModelAttribute 在参数上则自动注入到相应的ModelMap中,用在方法上则是在调用方法前,将返回值加入到ModelAndMap中
  • @RequestParam 请求的参数匹配到方法的入参中
  • @ExceptionHandler 异常时要执行的处理器
  • @ControllerAdvice 拦截异常并统一处理
  • @PathVariable 绑定 URL 占位符到入参,完成RESTFul风格。
	@RequestMapping(value="/user/{id}",method=RequestMethod.POST)
	public String post(@PathVariable("id") Integer id){
		// do something here
	}

THE END

好了,以上就是对于SpringMvc整体框架的介绍,这里我并没有给出一个完整的应用程序,因为我觉得这些内容才能够帮助我们更好的去理解整个框架,而单独的对于SpringMvc使用来讲还是相对比较简单的。我会在其他的博文中给出基于它的一个实际应用,还希望各位小伙伴持续关注哦~

当然以上只是个人的一些看法,如果有写的不好的或者是有问题的地方还希望您能与我联系,关注网站http://missxhh.com,获得更多有关于我的信息吧!

谢谢阅读,您的关注就是对我最大的动力!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值