spring源码分析-SpringMvc设计原理

1.三层架构与MVC架构的不同 三层架构 Dao(数据访问层) Service(业务处理层) Web(J2EE的内容,request和response)

MVC架构(web层) M:Model V:View C:Control

2.MVC框架的发展史 a)servlet(Server Applet)服务端应用程序

url与servlet通过web.xml配置映射,tomcat容器在启动的时候去读取配置文件,加载servlet到容器中,并且把url与servlet的映射关系存于map中,如此来完成url通过doGet与doPost访问一个web服务端应用程序,一般来说一个Servlet配置对应一个Url,这时候问题就出现了

view:JSP的底层就是一个Servlet,并且Jsp可以写java代码,没有真正的分离

–>问题:随着业务的越来越复杂,功能的新增,就会频繁的修改web.xml,导致代码膨胀,维护麻烦,多人开发起冲突
–>解决:mvc框架在这个背景就产生了

b)mvc框架(struts) 你只需要配置一个servlet,用来拦截所有的请求,这个控制中心再读取自己的配置,把url与类(普通的类)进行映射,以后新增需求只要对应的新增一个配置与类或者方法即可,不需要在改web.xml了,并且Model进行了一次很好的封装,能自动把参数转为对象,Form(提交过来的数据)+Action(管理url),每新增一个url请求就需要写两个类

view:FreeMarker新起(自己的语法,不能写java代码,支持标签)

–>问题:很伟大的发明,但是开发流程还是过于复杂,传参与配置过于麻烦
–>解决:springmvc推出,简化开发

c)成熟的mvc框架(springmvc) Url映射:把每一个url映射为某一个类的某个方法 Model:不强制要求(写Form类),可以作为一个方法的参数(自动转换) View:支持任意扩展(Jsp基本退出舞台,使用html)

3.Spring Mvc流程

a)初始化 (1)web.xml配置一个DispatchServlet(启动的入口) (2)程序开始扫描注解,把Bean加载到我们的IOC容器(ApplicationContext) (3)获取到IOC容器的Bean后开始扫描Ctrl层配置:注解(Controller/RequestMapping等),View的配置,插件(拦截器,转换器,视图解析器) (4)解析成一个HandleMapping的list(保存了url和具体的执行的方法对应关系),还有解析方法的参数保存在一个handlerAdapters的list里

b)用户访问 (1)从浏览器输入URL (2)统一拦截(扫描HandleMapping)404/500 (3)DispatchServlet接受到请求,从上面初始化已经保存的数据中找到请求url对应的方法,然后通过反射调用 (4)把相应结果输出,如果配置了模板,则解析读取模板,返回相应结果

c)主要部件
《spring源码分析-SpringMvc设计原理》

(1):DispatcherServlet是springmvc中的前端控制器(front controller),负责接收request并将request转发给对应的处理组件. (2):HanlerMapping是springmvc中完成url到controller映射的组件.DispatcherServlet接收request,然后从HandlerMapping查找处理request的controller. (3):Cntroller处理request,并返回ModelAndView对象,Controller是springmvc中负责处理request的组件(类似于struts2中的Action),ModelAndView是封装结果视图的组件. (4~6):视图解析器解析ModelAndView对象并返回对应的视图给客户端.

4.源码分析

(1)入口DIspatcherServlet->onRefresh->initStrategies
(2)initStrategies

 1//请求解析
 2initMultipartResolver(context);
 3//多语言、国际化
 4initLocaleResolver(context);
 5//主题View层的
 6initThemeResolver(context);
 7//============== 重要 ================
 8//解析url和Method的关联关系
 9initHandlerMappings(context);
10//适配器(匹配的过程)
11initHandlerAdapters(context);
12//============== 重要 ================
13//异常解析
14initHandlerExceptionResolvers(context);
15//视图转发(根据视图名字匹配到一个具体模板)
16initRequestToViewNameTranslator(context);
17//解析模板中的内容(拿到服务器传过来的数据,生成HTML代码)
18initViewResolvers(context);
19initFlashMapManager(context);

(3)核心方法 doDispatch
(4)MVC容器
/** handlerMappings存储的是请求url与方法的映射 /private List handlerMappings;/* 存储的是handler与参数的映射 */
private List handlerAdapters;

(5)web.xml配置解析

 1<context-param>
 2    <param-name>contextConfigLocation</param-name><!-- 属性在DispatcherServlet的父类FrameworkServlet中 -->
 3    <param-value>classpath:application-web.xml</param-value>
 4</context-param>
 5<listener>
 6    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 7</listener>
 8<servlet>
 9    <servlet-name>springmvc</servlet-name>
10    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
11    <init-param>
12        <param-name>contextClass</param-name><!-- 属性在DispatcherServlet的父类FrameworkServlet中 -->
13        <param-value>org.springframework.web.servlet.support.AnnotationConfigWebApplicationContext</param-value>
14    </init-param>
15    <load-on-startup>1</load-on-startup>
16</servlet>
17<servlet-mapping>
18    <servlet-name>springmvc</servlet-name>
19    <url-pattern>/</url-pattern>
20</servlet-mapping>

5.spring mvc的优化 (1)controller如果能保持单例,尽量使用单例,这样可以减少创建对象和回收对象的开销.也就是说,如果controller的类变量和实例变量可以以方法形参声明的尽量以方法的形参声明,不要以类变量和实例变量声明,这样可以避免线程安全问题. (2)处理request的方法中的形参务必加上@RequestParam注解,这样可以避免springmvc使用asm框架读取class文件获取方法参数名的过程.即便springmvc对读取出的方法参数名进行了缓存,如果不要读取class文件当然是更加好. (3)阅读源码的过程中,发现springmvc并没有对处理url的方法进行缓存,也就是说每次都要根据请求url去匹配controller中的方法url,如果把url和method的关系缓存起来,会不会带来性能上的提升呢?有点恶心的是,负责解析url和method对应关系的ServletHandlerMethodResolver是一个private的内部类,不能直接继承该类增强代码,必须要该代码后重新编译.当然,如果缓存起来,必须要考虑缓存的线程安全问题.

6.手写mvc框架 源码:
https://blog.csdn.net/charjay_lin/article/details/80948427

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/CharJay_Lin/article/details/81014034
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞