前文讲到了CSI技术,这就说明网站静态化技术的讲述已经推动到了浏览器端了即真正到了web前端的范畴了,而时下web前端技术的前沿之一就是先后端分离技术了,那么在这里网站静态化技术和先后端分离技术产生了交集,因此今天我将讨论下先后端分离技术,先后端分离技术讨论完后,下一篇文章我将会以网站静态化技术的角度回过头来从新审视下先后端分离技术,但愿经过这种审视来加深咱们对两套技术的理解。php
先后端分离技术我我的认为是web前端被专业化之后的必由之路,而nodejs的出现是先后端分离技术的一个强兴的催化剂,缘由是nodejs的出现削平了前端技术和服务端技术之间的鸿沟,使得先后端两套不一样技术体系进行真正意义的解耦提供了无限的可能性。可是若是咱们把nodejs技术的使用认为就是实现了先后端分离,这种理解又实在太肤浅了,下面我将讲讲我研究过的先后端分离技术方案,以及这些技术方案隐藏在背后思考,但愿这些思考能给你们以一个新的思路来理解先后端分离技术。css
咱们要深入理解先后端分离技术有一个重要的前提,那就是要把先后端分离技术认为是传统的web应用里的MVC设计模式的进一步演进。那么咱们首先来看看MVC的定义,下面的内容摘录于维基百科的解释,具体以下:html
MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。 MVC模式最先由Trygve Reenskaug在1978年提出[1] ,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式。MVC模式的目的是实现一种动态的程式设计,使后续对程序的修改和扩展简化,而且使程序某一部分的重复利用成为可能。除此以外,此模式经过对复杂度的简化,使程序结构更加直观。软件系统经过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。专业人员能够经过自身的专长分组: (控制器 Controller)- 负责转发请求,对请求进行处理。 (视图 View) - 界面设计人员进行图形界面设计。 (模型 Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(能够实现具体的功能)。
各种用于Web应用开发的语言里都有属于本身的MVC框架,例如本人最熟悉的服务端语言java里就有大名鼎鼎的struts2,springMVC的MVC应用框架,我早期从事java的web开发时候认为这些MVC框架都是很是的博大精深,用途普遍,可是当我逐渐转向了web前端技术开发之后又以为这些框架的不少功能显得那么的多余和累赘,所以我曾写过一篇文章专门讨论过这些问题,该文章的名字叫作《为何作java的web开发咱们会使用struts2,springMVC和spring这样的框架?》。前端
其实这篇文章被写的源头就是在于我认为像struts2和springMVC这样的框架作了太多浏览器自己就能够完成的工做,例如:页面的渲染操做,由于服务端抢了浏览器端的部分工做,这其实也就等于限制了web前端技术的深刻运用,像不少前端的优化技术以及不少提高用户体验的技术就很难派上用场,之因此产生这些问题,我认为传统的MVC框架本质实际上是一个服务端的MVC框架,虽然MVC设计模式里的V即View视图层是想把界面开发工做专业化,让界面设计人员能专心于界面开发,可是传统的MVC框架下的View层的本质倒是一个彻彻底底的服务端技术。java
咱们以java的web开发里jsp为例,JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是java里动态网页的技术标准,这就说明jsp虽然看起来像html,其实它并非真正的html,它须要被java的web容器进行解析转化为浏览器能够解析的html页面,而后经过网络传输到浏览器后,浏览器才能正确的展现这个jsp页面,其余web开发语言里都有相似的动态网页技术标准,可是无论什么语言的动态网页技术标准,咱们使用它时候就是让web前端技术被服务端技术所绑架,这也就是为何每一个招聘web前端工程师的岗位都要问你是否会java,php语言的源头。可是随着互联网的大发展,对web前端的要求是愈来愈专业化,web前端自己所包含的技术难度已经不亚于任何一个服务端语言开发难度,所以咱们须要web前端更高的专业化,而不但愿web前端工程师被服务端技术束缚的更多而限制了自身能力的发展,这就致使先后端分离技术的出现。node
不过先后端分离技术的第一阶段倒不是从改变view层即视图层开始的,而是从链接客户端和服务端的C层即控制层开始的,控制层既要做用于客户端又要做用于服务端,若是一个功能页面是一个程序员从浏览器端一直写到模型层,控制层也就不是什么问题了,可是若是当咱们想按MVC的设计思想,让界面开发人员专一于页面开发,服务端开发人员专一于服务端开发,那么这个时候控制层的归属问题就显的很是重要了。在传统的MVC框架里,由于M层和C层是使用一样的语言体系,所以咱们很天然会把M层和C层的开发工做都交由服务端开发人员完成,这个决定无可厚非,可是传统的MVC框架里V层和C层其本质也是同一个技术体系下的(例如java的web开发里的jsp本质就是个servlet),所以V层和C层也是紧耦合的,所以界面开发人员开发页面时候如何没有C层支撑,那么这个页面实际上是根本跑不起来的,若是前端开发人员这时候跑去写写C层即控制层的代码,这就打破了原有的横向分工,这个时候控制层的编码工做就会变得混乱而难以控制,看到这里有人必定会说既然控制层是属于服务端的,那么前端技术人员就等等服务端的开发进度,再不行就本身写个mock模拟下服务端的控制层,听到这种建议,我相信无论是前端的仍是服务端的技术人员都会头脑发麻,第一反应就是这不是自找麻烦啊,还不如一我的所有搞定算了。由此第一阶段的先后端分离技术方案出现了,这个方案须要解决的问题就是如何能让web前端技术人员和web服务端技术人员协同起来工做,合理的分工,换句话说就是按web前端和web服务端角度如何能横向的分解web的开发工做。程序员
先后端分离的第一阶段须要解决问题的核心就是控制层的归属问题,从技术角度而言就是控制层究竟是应该和视图层解耦比较合理仍是跟模型层解耦比较合理的问题。那么咱们这里先回顾下MVC设计模式里对控制层的定义,维基百科里的定义是:web
(控制器 Controller)- 负责转发请求,对请求进行处理。
不过这个解释我认为并不全面,以java的web开发里的控制层设计为例,咱们发现控制层以沟通视图层和模型层的角度而言,控制层其实主要完成三项具体的工做,它们分别是:算法
工做一:控制层起到一个路由的做用。客户端请求到达控制层后,控制层根据请求内容将请求路由到服务端某个模型层进行处理,模型层将请求处理完毕后,会把响应结果返回给控制层,控制层在根据响应信息路由到特定的页面。spring
工做二:控制层起到一个报文信息格式转化的做用。这里以java的web开发为例,浏览器的数据都是以http报文形式发送给服务端,而控制层就是将http报文信息解析成java的对象,固然也能够是java的基本数据类型,而后控制层把解析好的信息传递给模型层进行处理。
工做三:传统的MVC框架里,控制层其实深刻参入到了页面渲染的操做。在java的web开发里的控制层无论如何被包装,其本质就是一个servlet,而jsp页面本质也是个serlvet,所以咱们能够这么理解jsp,jsp就是以页面开发的方式写java,而servlet就是以java的方式写页面,因此咱们能够在servlet里以文件流的方式输出页面,也可让servlet跳转到jsp页面。
由上面的论述里咱们发现,其实传统MVC框架里控制层和模型层的联系方式相对很简单的,它们的联系主要是路由和报文格式的转化上,而控制层与视图层的联系除此以外还多了一个页面渲染,而页面渲染自己应该是属于浏览器的技术范畴,是浏览器技术不可分割的一部分,也是我上面内容里诟病传统MVC框架问题所在,若是控制层承担了页面渲染工做,那么控制层和视图层的耦合度就变得很是高,要想将其解耦是十分困难,通常只有咱们打破了现有MVC框架的技术体系才能完成,相比之下,控制层与模型层的解耦就显得容易多了。那么控制层与模型层如何解耦呢?具体以下:
首先咱们来解决下报文格式转化的问题,这个技术方案很简单就是借鉴http统一报文格式的特色,咱们为控制层和模型层定义一套统一的报文格式,例如咱们定义控制层和模型层都以map的数据类型进行数据传递,这个map里有个专门的字段用来定义被路由到的模型接口信息,有个字段专门存储须要传递的数据,具体的设计方案能够根据实际的业务须要来设计。
接下来就是路由的问题了,在解决报文格式转化问题的论述里我讲到要在统一报文格式里专门定义一个字段用来存储该数据到底路由到哪一个模型进行处理,不过这个字段并不能彻底解决路由问题,所以咱们须要模型层对控制层提供一个统一的接口,任何控制层与模型层的沟通都经过这个统一接口来完成,只不过不一样请求报文组装的内容不同而已,而这个接口还有个重要职责就是解析报文里的路由信息,让请求能被正确的路由到对应的模型接口所处理。固然这个接口的返回值最好也是一个统一的报文格式,这样控制层解析模型层的返回数据也会便利的多了。
由上所述,咱们发现第一阶段的先后端分离工做控制层应该归属于web前端,这么作更加合理,也更加容易实现,其实以后进化版的先后端分离方案,控制层也都是属于web前端,只不过形式不一样而已,这个我在下一篇文章里继续讨论。
第一阶段先后端分离方案解决的核心就是让控制层和模型层解耦,这个方案进一步演化一下,咱们能够把控制层和视图层独立成一个web应用,模型层也独立成一个web应用,两个web应用之间经过远程调用方式进行沟通,这个方案我在之前文章里写过,这篇文章的名字叫作《我设计的网站的分布式架构》。
这个进化版的方案增长了系统开发的难度,由于咱们须要增长网络通讯的编程以及远程调用的实现,更麻烦的是咱们还须要进行复杂的多线程编程,既然增长了开发的难度为何我还要这么作呢?首先咱们经过应用分层,能够动态的调节web前端和web服务端的负载压力,还能够在模型层以前提供一道安全屏障,不过被服务端绑架的web前端在提高整个web应用负载能力这块仍是颇有限的,其实这种作法的最大好处就是利于SOA框架的设计,也就是说这种架构咱们能够为服务端的SOA化提供有力的保障,由于控制层和模型层的解耦,可让模型层真正作到专一于业务,而不会再发生那种把业务逻辑写到控制层的问题了从而下降代码的健壮性。