本文节选自《Spring 5外围原理》
1 什么是Spring MVC
Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,实质上相当于 Servlet。Spring MVC 角色划分清晰,分工明细。因为 Spring MVC 自身就是 Spring 框架的一部分,能够说和 Spring 框架是无缝集成。性能方面具备先天的优越性,是当今业界最支流的 Web 开发框架,最热门的开发技能。
首先从一个由Spring提供的DispatcherServlet开始,重写了Serlvet的init()办法、service()办法和destroy()办法,SpringMVC九大组件在DispatcherServlet的init()办法中初始化,在service()办法中执行。上面,咱们先来看Spring MVC九大组件的初始化。
2 SpringMVC九大组件名称解释
Spring MVC九大组件在DispatcherServlet的init()办法中初始化,上面我具体介绍一下Spring MVC九大组件的名称和作用。
序号 | 组件名 | 解释 |
---|---|---|
1 | MultipartResolver | 用于解决多文件上传申请。 |
2 | LocaleResolver | 用于从申请中解析出 Locale,是i18n的根底。 |
3 | ThemeResolver | 用来解析款式、图片及它们所造成的显示成果的汇合。 |
4 | HandlerMapping | 保留Url和逻辑解决的映射关系, |
5 | HandlerAdapter | 动静参数适配器,让固定的Servlet解决办法调用Handler来进行解决 |
6 | HandlerExceptionResolver | 用来解决Handler产生的异常情况的组件。 |
7 | RequestToViewNameTranslator | 从申请中获取ViewName |
8 | ViewResolvers | 次要作用是将String类型的视图名和Locale解析为View类型的视图 |
9 | FlashMapManager | 用于重定向时的参数传递。 |
具体具体介绍如下:
2.1 MultipartResolver
MultipartResolver是一个大家很相熟的组件,用于解决上传申请,通过将一般的申请包装成MultipartHttpServletRequest来实现。MultipartHttpServletRequest能够通过getFile()办法间接取得文件。如果上传多个文件,还能够调用getFileMap()办法失去 Map< FileName, File> 这样的构造。MultipartResolver的作用就是封装一般的申请,使其领有文件上传的性能。
2.2 LocaleResolver
ViewResolver组件的resolveViewName()办法须要两个参数,一个是视图名,另一个就是Locale。参数Locale是从哪来的呢?这就是LocaleResolver组件要做的事。LocaleResolver用于从申请中解析出 Locale,比方在中国Locale当然就是zh-CN,用来示意一个区域。这个组件也是i18n的根底。
2.3 ThemeResolver
从名字便可看出,ThemeResolver组件是用来解析主题的。主题就是款式、图片及它们所造成的显示成果的汇合。Spring MVC中一套主题对应一个properties文件,外面寄存着与以后主题相干的所有资源,如图片、CSS款式等。创立主题非常简单,只需筹备好资源,而后新建一个“主题名.properties”并将资源设置进去,放在classpath下,之后便能够在页面中应用了。Spring MVC中与主题无关的类有ThemeResolver、ThemeSource和Theme。ThemeResolver负责从申请中解析出主题名,ThemeSource则依据主题名找到具体的主题,其形象也就是Theme,能够通过Theme来获取主题和具体的资源。
2.4 HandlerMapping
HandlerMapping是用来查找Handler的,也就是处理器,具体的表现形式能够是类,也能够是办法。比方,标注了@RequestMapping的每个办法都能够看成一个Handler。Handler负责理论的申请解决,在申请达到后,HandlerMapping的作用便是找到申请相应的处理器Handler和Interceptor。
2.5 HandlerAdapter
从名字上看,HandlerAdapter是一个适配器。因为Spring MVC中Handler能够是任意模式的,只有可能解决申请便可。然而把申请交给Servlet的时候,因为Servlet的办法构造都是doService(HttpServletRequest req, HttpServletResponse resp)模式的,要让固定的Servlet解决办法调用Handler来进行解决,这一步工作便是HandlerAdapter要做的事。
2.6 HandlerExceptionResolver
从组件的名字上看,HandlerExceptionResolver是用来解决Handler产生的异常情况的组件。具体来说,此组件的作用是依据异样设置ModelAndView,之后交给渲染办法进行渲染,渲染办法会将ModelAndView渲染成页面。不过要留神,HandlerExceptionResolver只用于解析对申请做解决阶段产生的异样,渲染阶段的异样不归它管,这也是Spring MVC 组件设计的一大准则—分工明确、互不干涉。
2.7 RequestToViewNameTranslator
RequestToViewNameTranslator组件的作用是从申请中获取ViewName。因为ViewResolver依据ViewName查找View,但有的Handler解决实现之后,没有设置View,也没有设置ViewName,便要通过这个组件来从申请中查找ViewName。
2.8 ViewResolver
ViewResolver即视图解析器,置信大家对这个组件应该很相熟了。通常在Spring MVC的配置文件中,都会配上一个实现类来进行视图解析。这个组件的次要作用是将String类型的视图名和Locale解析为View类型的视图,只有一个resolveViewName()办法。从办法的定义能够看出,Controller层返回的String类型的视图名viewName最终会在这里被解析成为View。View是用来渲染页面的,也就是说,它会将程序返回的参数和数据填入模板中,生成HTML文件。ViewResolver在这个过程中次要做两件小事:ViewResolver会找到渲染所用的模板(第一件小事)和所用的技术(第二件小事,其实也就是找到视图的类型,如JSP)并填入参数。默认状况下,Spring MVC会为咱们主动配置一个InternalResourceViewResolver,是针对JSP类型视图的。
2.9 FlashMapManager
说到FlashMapManager组件,得先说一下FlashMap。
FlashMap用于重定向时的参数传递,比方在解决用户订单时,为了防止反复提交,能够解决完post申请后重定向到一个get申请,这个get申请能够用来显示订单详情之类的信息。这样做尽管能够躲避用户从新提交订单的问题,然而在这个页面上要显示订单的信息,这些数据从哪里获取呢?因为重定向是没有传递参数这一性能的,如果不想把参数写进URL(其实也不举荐这么做,除了URL有长度限度,把参数都间接裸露也不平安),那么就能够通过FlashMap来传递。只须要在重定向之前将要传递的数据写入申请(能够通过ServletRequestAttributes.getRequest()办法取得)的属性OUTPUT_FLASH_MAP_ATTRIBUTE中,这样在重定向之后的Handler中Spring就会主动将其设置到Model中,在显示订单信息的页面上就能够间接从Model中取得数据。
FlashMapManager就是用来治理FlashMap的。
3 Spring MVC要害组件的执行流程
Spring MVC九大组件的执行在DispatcherServlet的service()办法中实现。在这里,我重点介绍几个要害组件HandlerMapping、HandlerAdapter、ViewResolver在service()办法中的执行流程,具体调用分为以下几个步骤:
1、HandlerMapping回到调用HandlerAdapter
2、HandlerAdapter会返回ModelAndView
3、ModelAndView依据用户传入参数失去ViewResolvers
4、ViewResolvers会将用户传入的参数封装为View,交给引擎进行渲染。
上面给大家分享一张Spring MVC要害组件的执行流程图,以帮忙大家更好地了解:
留神:上图中有大家最相熟的两个类:ModelAndView和View类并不属于Spring MVC九大组件之列。
4 Spring MVC优化倡议
后面咱们曾经对Spring MVC的工作原理和源码进行了剖析,在这个过程中有几个优化点。
1. Controller如果能放弃单例模式,尽量应用单例模式
这样能够减小创建对象和回收对象的开销。也就是说,如果Controller的类变量和实例变量能够以办法形参申明就尽量以办法形参申明,不要以类变量和实例变量申明,这样能够防止线程平安问题。
2. 解决申请的办法中的形参务必加上@RequestParam注解
这样能够防止Spring MVC应用asm框架读取.class文件获取办法参数名。即使Spring MVC对读取出的办法参数名进行了缓存,如果能不读取.class文件当然更好。
3. 缓存URL
在浏览源码的过程中,咱们发现Spring MVC并没有对解决URL的办法进行缓存,也就是说,每次都要依据申请URL去匹配Controller中的办法的URL,如果把URL和办法的关系缓存起来,会不会带来性能上的晋升呢?可怜的是,负责解析URL和办法对应关系的ServletHandlerMethodResolver是一个公有的外部类,不能间接通过继承该类加强代码,必须在代码后从新编译。当然,如果将URL缓存起来,必须思考缓存的线程平安问题。
关注微信公众号『 Tom弹架构 』回复“Spring”可获取残缺源码。
本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我高兴!如果您有任何倡议也可留言评论或私信,您的反对是我保持创作的能源。关注微信公众号『 Tom弹架构 』可获取更多技术干货!
原创不易,保持很酷,都看到这里了,小伙伴记得点赞、珍藏、在看,一键三连加关注!如果你感觉内容太干,能够分享转发给敌人滋润滋润!