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分享。
1 |
|
2 | <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
3 | xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" |
4 | xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" |
5 | version="3.0"> |
6 | <display-name>smvc</display-name> |
7 | <listener> |
8 | <description>spring日志监听器</description> |
9 | <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> |
10 | </listener> |
11 | <listener> |
12 | <description>spring监听器</description> |
13 | <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> |
14 | </listener> |
15 | <listener> |
16 | <description>request监听器</description> |
17 | <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> |
18 | </listener> |
19 | <listener> |
20 | <description>系统初始化监听器</description> |
21 | <listener-class>org.jeecgframework.web.system.listener.InitListener</listener-class> |
22 | </listener> |
23 | <!-- 核心控制器 --> |
24 | <servlet> |
25 | <description>spring mvc servlet</description> |
26 | <servlet-name>springMvc</servlet-name> |
27 | <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> |
28 | <init-param> |
29 | <description>spring mvc 配置文件</description> |
30 | <param-name>contextConfigLocation</param-name> |
31 | <param-value>classpath*:spring-mvc.xml</param-value> |
32 | </init-param> |
33 | <load-on-startup>1</load-on-startup> |
34 | </servlet> |
35 | <servlet-mapping> |
36 | <servlet-name>springMvc</servlet-name> |
37 | <url-pattern>*.do</url-pattern> |
38 | </servlet-mapping> |
39 | <servlet-mapping> |
40 | <servlet-name>springMvc</servlet-name> |
41 | <url-pattern>*.action</url-pattern> |
42 | </servlet-mapping> |
43 | <!-- restUrl风格配置 --> |
44 | <servlet> |
45 | <servlet-name>restSpringMvc</servlet-name> |
46 | <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> |
47 | <init-param> |
48 | <description>spring mvc 配置文件</description> |
49 | <param-name>contextConfigLocation</param-name> |
50 | <param-value>classpath*:spring-mvc.xml</param-value> |
51 | </init-param> |
52 | </servlet> |
53 | <servlet-mapping> |
54 | <servlet-name>restSpringMvc</servlet-name> |
55 | <url-pattern>/rest/*</url-pattern> |
56 | </servlet-mapping> |
57 | </web-app> |
spring-mvc.xml的部分配置:
1 | <!-- 自动扫描controller包下的所有类 --> |
2 | <context:component-scan base-package="com.*.*"> |
3 | <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> |
4 | </context:component-scan> |
5 | <!-- IE执行AJAX时配置 --> |
6 | <bean id="mappingJacksonHttpMessageConverter" |
7 | class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> |
8 | <property name="supportedMediaTypes"> |
9 | <list> |
10 | <value>text/html;charset=UTF-8</value> |
11 | <value>text/json;charset=UTF-8</value> |
12 | <value>application/json;charset=UTF-8</value> |
13 | </list> |
14 | </property> |
15 | </bean> |
16 | <!-- 注册RequestMappingHandlerMapping --> |
17 | <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> |
18 | <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> |
19 | <!-- 默认的视图解析器- --> |
20 | <bean id="defaultViewResolver" |
21 | class="org.springframework.web.servlet.view.InternalResourceViewResolver" |
22 | p:order="3"> |
23 | <property name="viewClass" |
24 | value="org.springframework.web.servlet.view.JstlView" /> |
25 | <property name="contentType" value="text/html" /> |
26 | <property name="prefix" value="/webpage/" /> |
27 | <property name="suffix" value=".jsp" /> |
28 | </bean> |
29 | <bean id="multipartResolver" |
30 | class="org.springframework.web.multipart.commons.CommonsMultipartResolver" |
31 | p:defaultEncoding="UTF-8"> |
32 | <property name="maxUploadSize"> |
33 | <value>104857600</value> |
34 | </property> |
35 | <property name="maxInMemorySize"> |
36 | <value>4096</value> |
37 | </property> |
38 | </bean> |
39 | <!-- Bean解析器 --> |
40 | <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风格。
1
"/user/{id}",method=RequestMethod.POST) (value=
2
public String post(@PathVariable("id") Integer id){
3
// do something here
4
}
THE END
好了,以上就是对于SpringMvc整体框架的介绍,这里我并没有给出一个完整的应用程序,因为我觉得这些内容才能够帮助我们更好的去理解整个框架,而单独的对于SpringMvc使用来讲还是相对比较简单的。我会在其他的博文中给出基于它的一个实际应用,还希望各位小伙伴持续关注哦~
当然以上只是个人的一些看法,如果有写的不好的或者是有问题的地方还希望您能与我联系,关注网站http://missxhh.com,获得更多有关于我的信息吧!
谢谢阅读,您的关注就是对我最大的动力!!!