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

0.239字数 4206阅读 1970

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


第一篇  网站基础知识

第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结构

推荐阅读更多精彩内容