美文网首页SpringJava技术升华
《看透SpringMVC源代码分析与实践》学习笔记(持续更新……

《看透SpringMVC源代码分析与实践》学习笔记(持续更新……

作者: 波波波先森 | 来源:发表于2018-08-20 21:44 被阅读68次

        本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那就点个小心心,文末赞赏一杯豆奶吧,嘻嘻。 让我们共同成长吧……


    第一篇  网站基础知识

    第1章  网站架构及其演变过程

    1.1  软件的三大类型

            单机类型,CS类型,BS类型

    1.2    基础架构并不简单

            BS结构网络传输的分解方式有两种:一种是标准的OSI参考模型;另一种是TCP/IP参考模型。

            OSI参考模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

            TCP/IP参考模型:网络接入层、网际互联层、传输层、应用层

            对于TCP/IP参考模型的4层的理解:

            BS结构中,网络接入层没有相应协议,网际互联层是IP协议,传输层是TCP协议,应用层是HTTP协议。还用到了DNS协议。

    1.3  架构演变的起点

    1.4  海量数据的解决方案

        1.4.1    缓存和页面静态化

            缓存使用方式:通过程序直接保存在内存中和使用缓存框架。程序直接操作主要是使用Map,尤其是ConcurrentHashMap,常用的缓存框架有Ehcache、Memchache和Redis。缓存主要适用于数据变化不是很频繁的情况,如果是定期失效的失效机制,实时性也不能要求太高。

            页面静态化是将程序最后生成的页面保存起来,页面静态化对数据量大、并发量高两大问题都有好处。页面静态化可以在程序中使用模板技术生成,例如Freemarker、Velocity.也可以使用缓存服务器再应用服务器的上一层缓存生成的页面,例如Nginx、Squid。

        1.4.2  数据库优化

            常见的数据库优化:表结构优化、SQL语句优化、分区和分表、索引优化、使用存储过程代替直接操作、合理使用冗余。

        1.4.3    分离活跃数据

        1.4.4    批量读取和延迟修改

        1.4.5    读写分离

        1.4.6  分布式数据库

        1.4.7    NoSQL和Hadoop    

    1.5    高并发的解决方案

        应用和静态资源分离、页面缓存、集群与分布式、反向代理、CDN

    1.6  底层的优化

    1.7  小结



    第2章    常见协议和标准

    2.1  DNS协议

            DNS作用是将域名解析为IP.

    2.2    TCP/IP协议与Socket

            TCP在传输之前会进行三次沟通,称作“三次握手”,传完数据断开时要进行四次沟通,称作“四次挥手”。TCP中的两个序号和三个标志位的含义:

            seq:表示传输数据的序号。ack:表示确认号。ACK:确认位。SYN:同部位。FIN:终止位。

    2.3  HTTP协议

            HTTP中的报文分为:请求报文、响应报文。这两种类型都包括:首行、头部和主体。

    HTTP报文结构

            请求报文中的方法指:GET、HEAD、POST、PUT、DELETE,响应报文中的状态码分为5类:

    5种类型的状态码

    2.4    Servlet与Java Web开发

            Servlet是J2EE标准的一部分,是JavaWeb开发的标准。Servlet的作用是对接收到的数据进行处理并生成要返回给客户端的结果。要想使用Servlet需要相应的Servlet容器,常见的Servlet容器时Tomcat.

    第3章    DNS的设置

    第4章    Java中Socket的用法

        本章介绍Java中的Socket的用法,Java中的Socket分为普通Socket和NioSocket两种。

    4.1  普通Socket用法

            Java中的网络通信通过Socket实现的,Socket分为ServerSocket和Socket两大类。ServerSocket用于服务端,可以通过accept()方法监听请求返回Socket,Socket用于具体完成数据传输。客户端直接使用Socket发起请求并传输数据。

            ServerSocket的使用分为三步:

            1)创建ServerSocket。

            2)调用创建出来的ServerSocket的accept方法。

            3)使用accept方法返回Socket与客户端进行通信。

            Socket客户端使用:创建一个Socket,和服务器进行通行,传输数据,释放连接。

    4.2  NioSocket的用法

            ServerSocketChannel和SocketCHannel,分别对应以前的ServerSocket和Socket。

            NioSocket中服务端的处理过程步骤:

            1)创建ServerSocketChannel并设置相应采参数

            2)创建Selector并注册到ServerSocketChannel

            3)调用Selector的select方法等待请求

            4)Selector接收请求后使用selectedKeys返回SelectionKey集合

            5)使用SelectionKey获取到Channel、Selector和操作类型并进行具体的操作。



    第5章  自己动手实现HTTP协议

    第6章  详解Servlet

            Servlet是Server+Applet的缩写,表示一个服务器应用。Servlet是一套规范。按照此规范编写的代码就能在java的服务器上运行。

    Servlet结构图

    6.1  Servlet接口

    Servlet接口定义

            init方法:容器启动时被容器调用,只会调用一次。

            getServletConfig方法:用于获得ServletConfig.

            service方法:用于具体处理一次请求。

            getServletInfo方法:获取一些Servlet相关信息,如作者、版权等。

            destroy方法:主要用于Servlet销毁时释放一些资源,只会调用一次。

            在web.xml中定义Servlet时通过init-param标签配置的参数就是通过Servlet来保存的。Tomcat中的Servletinit方法是在ocrg.apache.catalina.core.StandardWrapper的initServlet方法中调用的,ServletConfig传入的是StandardWrapper自身的门面类StandardWrapperFacade。

    ServletConfig接口

            ServletConfig(Servlet级别)和ServletContext(Application级别)是最常见的传递初始化参数的。

    6.2  GenericServlet

            GenericServlet是Servlet的默认实现,主要做了三件事:实现ServletConfig接口,可以直接调用ServletConfig里面的方法;提供了无参的init方法;提供了log方法。

            GenericServlet实现了ServletConfig,可以在需要用ServletConfig中的方法的时候可以直接调用,而不需要先获取ServletConfig,不过底层还是使用ServletConfig进行调用。

             GenericServlet实现了Servlet的init(ServletConfig  config)方法,现将config设置给了内部变量config,然后调用了无参的init()方法,这个方法是模板方法,子类可以通过覆盖它来完成自己的初始化工作。

            GenericServlet提供了2个log方法,一个记录日志,一个记录异常,具体实现是通过传给ServletContext的日志实现的。

    6.3  HttpServlet

            HttpServlet是HTTP协议实现的Servlet的基类,HttpServlet主要重写了service方法,首先将ServletRequest和ServletResponse转换为了HttpServletRequest和HttpServletResponse,然后根据http请求的类型不同将请求路由到了不同的处理方法。



    第7章 Tomcat分析

    7.1  Tomcat的顶层结构及启动过程

    7.1.1  Tomcat的顶层结构

            Tomcat最顶层的容器时Server,代表整个服务器,Server中包含至少一个Service,应用于具体提供服务。Service主要包含:Connector和Container。Connector用于处理连接相关的事情,并提供Socket与request、response的转换;Container用于封装和管理Servlet以及具体的request请求。一个Tomcat只有一个Server,一个Server可以包含多个Service,一个Service包含多个Connector,但只包含一个Container。

    Tomcat整体结构图

            Tomcat里的Server有Catalina来管理,里面有三个方法:load、start、stop,分别用来管理整个服务器的生命周期。Tomcat的入口main方法在Bootstrap中。

    7.1.2  Bootstrap的启动过程

            Bootstrap是Tomcat的入口,正常情况下Tomcat就是调用Bootstrap的main方法:

            main方法主要有两部分内容:首先新建了Bootstrap,并执行init方法初始化;然后处理main方法传入的命令,如果args参数为空,默认执行start方法。

            在init方法中初始化了ClassLoader,并使用ClassLoader创建Catalina实例,然后赋值给catalinaDaemon变量。对start的处理,通过反射调用了Catalina的setAwait(true)、load(args)、start()三个方法。

    7.1.3  Catalina的启动过程

            从前面可知,catalina的启动主要是调用setAwait、load、start来完成的。setAwait用于设置Server启动完成之后是否进入等待状态标志;load用于加载配置文件,创建并初始化Server;start用于启动服务器。

    setAwait方法 load方法 start方法

    7.1.4  Server的启动过程

            Server接口中提供addService(Service service)、removeService(Service service)来添加和删除Service,Server的init和start方法分别循环调用每个Service的init和start方法来启动所有的Service。

            Server的默认实现是StandardServer,StandardServer继承自LifecycleMBeanBase,LifecycleMBeanBasej继承自LifecycleBase,init和start方法就在LifecycleBase中,LifecycleBase里的init和start又调用了initInternal和startInternal方法,这两个方法是模板方法。所以调用StandardServer的init和start方法会执行StandardServer自己的initInternal和startInternal方法,这就是Tomcat生命周期的管理方式。

            StandardServer还实现了await方法,Catalina中就是让调用它的服务器进入等待执行状态。

    7.1.5  Service的启动过程

            Service默认实现是:StandardService,继承自LifecycleMBeanBasej,init和start方法最终会调用initInternal和startInternal方法.

            现在整个Tomcat服务器就启动了,整个启动流程:

    Tomcat顶层组件启动时序图

    7.2  Tomcat的生命周期管理

    7.2.1  Lifecycle接口

            Tomcat通过org.apache.catalina.Lifecycle接口统一管理生命周期,所有有生命周期的组件都需要实现Lifecycle接口。

    Lifecycle接口定义

    7.2.2  LifecycleBase

            LifecycleBase默认实现是org.apache.catalina.util.LifecycleBase,所有实现了生命周期的组件都直接或者间接的继承LifecycleBase。LifecycleBase为Lifecycle里的接口方法提供了默认实现:监听器管理使用LifecycleSupport类完成。

            三个管理监听器的方法:

            四个生命周期方法:

            两个获取当前状态的方法:

    7.3  Container

    7.4  Pipeline-Value管道

    7.5  Connector分析



    第二篇  俯视Spring MVC

    第8章 Spring MVC之初体验

            本章主要介绍SpringMVC的环境搭建并简单介绍使用方法。

    8.1  环境搭建

    8.2  Spring MVC最简单的配置

            配置一共需要三步:在web.xml中配置Servlet;创建SpringMVC的xml文件;创建Controller和view。

    8.2.1  在web.xml中配置Servlet

    8.2.2  创建SpringMVC的xml文件

    8.2.3  创建Controller和view

    8.3  关联sprin源代码



    第9章 创建SpringMVC之器

            本章分析SpringMVC创建过程

    9.1  整体结构介绍

            Spring MVC中核心Servlet的继承结构:

    Spring MVC中核心Servlet的继承结构

    9.2  HttpServletBean

            通过前面对Servlet的分析,可知道Servlet创建可以直接调用无参的init方法,HttpServletBean的init方法如下:

            在HttpServletBean的init中,首先,将Servlet中配置的参数使用BeanWrapper设置到DispatcherServlet的相关属性;然后调用模板方法initServletBean,子类通过该方法初始化。

    9.3  FrameworkServlet

            从HttpServletBean可知,FrameworkServlet的入口是initServletBean,

            FrameworkServlet主要做了两件事:初始化WebApplicationContext;初始化FrameworkServlet,initFrameworkServlet是个模板方法,子类可以覆盖后在里面做一些初始化的工作,但是子类并没有使用它。

            initWebApplicationContext方法做了三件事:1)获取spring的根容器rootContext;    2)设置WebApplicationContext并根据情况调用onRefresh方法;    3)将WebApplicationContext设置到ServletContext中

            获取spring的根容器rootContext

            默认情况下spring会将自己的容器设置成ServletContext的属性,默认的根容器的key是org.springframwork.web.context.WebApplicationContext.ROOT,它的定义在org.springframwork.web.context.WebApplicationContext中。

           设置WebApplicationContext并根据情况调用onRefresh方法

            设置WebApplicationContext方法有三:

                (1) 在构造方法中已经传递WebApplicationContext参数,这是只需要进行一些设置就可以了。

                (2)WebApplicationContext已经存在在ServletContext中,这时只需要配置Servlet时将ServletContext中的WebApplicationContext的name配置到contextAttribute属性就可以了。例如ServletContext中有个叫haha的WebApplicationContext,可以如下设置:

                (3)自己创建一个WebApplicationContext。正常情况下使用的该方式。创建过程在createWebApplicationContext方法中,createWebApplicationContext内部有调用了configureAndRefreshWebApplicationContext方法:

            需要注意的是,在configureAndRefreshWebApplicationContext方法中为wac添加了监听器,

            SourceFilteringListener可以根据参数进行选择,所以实际监听的是ContextRefreshListener所监听的事件。ContextRefreshListener是FramewoServlet的内部类,监听ContextRefreshedEvent事件,

            再回到initWebApplicationContext方法,可以看到后面根据refreshEvenReceived标志来判断是否要运行onRefresh.

            设置WebApplicationContext的三种方法中,第一种和第三种都已经refresh过了,只有第二种没有,会调用onRefresh。onRefresh只会别调用一次,而DispatcherServlet正是通过重写该方法实现初始化的。

            将WebApplicationContext设置到ServletContext中

            最后,根据publishContext标志判断是否将创建出来的WebApplicationContext设置到ServletContext中。

    9.4  DispatcherServlet

            onRefresh方法是DispatcherServlet的入口方法。

            initStrategies就是初始化9个组件,以LocalResolver为例分析具体的初始化方式:

    需要注意的是,context指的是WebApplicationContext,而不是ServletContext。

            className来自classNames,calssNames又来自value,value来自defaultStragies.getProperty(key).

            defaultStragies是DispatcherServlet类所在包下的DEFAULT_STRATEGES_PATH文件定义的属性,值是DispatcherServlet.properties。

    9.5  小结

            HttpServletBean:作用是将Servlet中配置的参数设置到相应的属性

            FreamworkServlet:初始化WebApplicationContext、初始化FreamworkServlet

            DispatcherServlet:初始化自身的9个组件



    第10章  SpringMVC之用

            本章分析SpringMVC是如何运行的,是怎么处理请求的。首先分析HttpServletBean、FreamworkServlet和DispatcherServlet这三个Servlet,目的是明白Servlet容器将请求交

    10.1  HttpServletBean

            HttpServletBean在处理请求中没有涉及相应的请求处理。

    10.2  FrameworkServlet

            Servlet处理过程:从Servlet的service方法开始,然后再HttpServlet的service方法中根据不同类型将请求路由到doGet、doHead、doPost、doPut、doDelete、doOption、doTrace,并做了doHead、doOption、doTrace的默认实现。

            FrameworkServlet重写了service、doGet、doPost、doPut、doDelete、doOption、doTrace,在service增加了对PATCH类型的处理

            以下是service和doGet的代码:

            由上可以看出,将请求合并到processRequest中。

            LocaleContext:存放着Locale(本地化信息);RequestAttributes:是spring的一个接口,通过它可以get/set/removeAttribute,根据scope参数判断操作request还是session,具体使用的是ServletRequestAttributes,ServletRequestAttributes里面封装了request、response、session,通过get就可以获得。

            LocaleContextHolder,是抽象类,里面的方法是static的,可以直接使用。

            RequestContextHolder也是一样的道理。

            FrameworkServlet工作流程:首先,在service方法中添加对PATCH的处理,并将所需要自己处理的请求集中到processRequest进行统一处理。然后,processRequest将处理逻辑交给模板方法doService,在doService的的前后使用request获取LocaleContexthe和RequestAttributes进行保存,处理完之后恢复。最后,发布ServletRequesthandledEvent事件。

    10.3  DispatcherServlet

            DispatcherServlet里面执行处理的入口方法是doService。doService将处理交给doDispatch进行具体处理,在doDispatch处理前doService做了一些事情:首先判断是不是include请求,如果是则对request的Attribute做个快照备份,等doDispatch处理完之后进行还原,

            对request设置的属性中,前面4个属性webApplicationContext、localeResolver、themeResolver和themeSource在Handler和view中使用。后面3个属性都和flashMap相关,主要用于Redirect转发是参数的传递。

            doDispatch的任务:(1)根据request找到Handler    (2)根据Handler找到对应的HandlerAdapter    (3)用HandlerAdapter处理Handler   (4)调用processDispatchResult方法处理上面处理之后的返回结果。

            Hanlder :处理器,直接对应MVC中的C.

            HandlerMapping :用来查找Handler.

            handlerAdapter :适配器,调用具体的Handler对请求进行处理。

    10.4  doDispatch结构

    相关文章

      网友评论

        本文标题:《看透SpringMVC源代码分析与实践》学习笔记(持续更新……

        本文链接:https://www.haomeiwen.com/subject/yjqlbftx.html