前后端分离:互联网项目开发的业界标准使用方式
一、背景前后端分离已经成为互联网项目开发的行业标准方法。通过nginx+可以有效解耦(也可以中间加一个),前后端分离将为未来大规模分布式架构、弹性计算架构、微服务提供基础。架构、多终端服务(多客户端,如浏览器、车载终端、、IOS等)打下坚实的基础。这一步是系统架构从猿进化到人的必经之路。
核心思想是前端HTML页面通过AJAX调用后端API接口,与JSON数据进行交互。
一般情况下,外网只能访问Web服务器,内网只能访问应用服务器。
在以前的大多数Java Web项目中,Java程序员既是父亲又是母亲,既从事前端又从事后端。随着时代的发展,很多大中小型公司也逐渐开始将前后端的界限区分得越来越清晰。前端工程师只负责前端的事情,后端工程师只负责后端的事情。俗话说,艺有专攻。如果一个人什么都知道,那么他终究什么都不擅长。大中型企业需要专业人才,小企业需要通才。但为了个人职业发展,前后端需要分开。
2、不分离的时代(各种耦合)
早期主要使用MVC框架。 Jsp+的结构图如下:
基本上,所有请求都发送到控制器,控制器接受请求并根据请求信息将它们分发到适当的 JSP 进行响应。同时,还根据JSP需求生成实例并输出到JSP环境。 JSP中的数据可以通过直接调用方法或者使用自定义标签来获取。
需要注意的是,这个View还可以使用 、 等模板引擎。使用这些模板引擎可以使开发过程中的分工更加清晰,提高开发效率。
所以,这个时期有两种开发方式:
方法一
方法2
方法2已逐渐被淘汰。主要原因有两个:
因此,方法2逐渐不被采用。不过,不得不说,方法一其实至今仍然被很多小型传统软件公司所采用。那么,方法1和方法2有哪些共同的缺点呢?
1、前端无法独立调试,开发效率低;
2.前端难免会遇到后端代码,比如:
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre style="max-width: 100%;letter-spacing: 0.544px;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code class="" style="margin-right: 2px;margin-left: 2px;padding: 0.5em;max-width: 100%;font-size: 12px;color: white;line-height: 15px;border-radius: 0px;background: rgb(51, 51, 51);font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;word-spacing: -3px;letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span class="" style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="" style="max-width: 100%;color: rgb(98, 200, 243);line-height: inherit;"><<span class="" style="max-width: 100%;color: inherit;line-height: inherit;font-weight: bold;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">body</span>></span><br style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"/> <%<br style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"/> <span class="" style="max-width: 100%;color: rgb(255, 255, 170);line-height: inherit;">request</span>.setCharacterEncoding(<span class="" style="max-width: 100%;color: rgb(162, 252, 162);line-height: inherit;">"utf-8"</span>)<br style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"/> <span class="" style="max-width: 100%;color: rgb(255, 255, 170);line-height: inherit;">String</span> name=<span class="" style="max-width: 100%;color: rgb(255, 255, 170);line-height: inherit;">request</span>.getParameter(<span class="" style="max-width: 100%;color: rgb(162, 252, 162);line-height: inherit;">"username"</span>);<br style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"/> out.print(name);<br style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"/> %><br style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"/><span class="" style="max-width: 100%;color: rgb(98, 200, 243);line-height: inherit;"></<span class="" style="max-width: 100%;color: inherit;line-height: inherit;font-weight: bold;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">body</span>></span><br style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"/></span></code></pre></p>
这种方法耦合性太强。那么,即使使用其他模板引擎,也无法编写Java代码。前端不可避免地要重新学习模板引擎的模板语法,这会无谓地增加前端的学习成本。就像我们不想在后端开发中写前端一样,想想如果前端代码嵌入到你的后端代码中你会作何感想?因此,这种做法是非常不合适的。
https://i2.hdslb.com/bfs/archive/89f1a9db7296a4870d4655ba277db48f07d1aa22.png
3、JSP本身引起的一些其他问题。例如,JSP第一次运行时比较慢,因为它包含将JSP翻译成的步骤。再比如,由于是同步加载,当JSP中的内容很多时,页面响应会很慢。
3、半分离时代
前端和后端是半分离的。前端负责开发页面,通过接口(Ajax)获取数据,使用Dom操作对页面进行数据绑定,最后前端渲染页面。这就是 Ajax 与 SPA 应用程序(单页应用程序)结合的方式。结构图如下:
步骤如下:
后端提供JSON格式的API接口供最终使用,提供给WEB的API接口也是JSON格式的。
那么说明WEB的工作流程是:
这些步骤是由用户所使用的设备逐步执行的,这意味着用户设备的性能与APP的运行速度关系更为密切。也就是说,如果用户的设备非常低端,APP打开页面的速度就会变慢。 。
为什么说是半分离呢?因为并非所有页面都是单页面应用程序。在多页面应用的情况下,由于前端没有控制层,因此前端需要与后端进行讨论。我们的页面应该同步输出,还是异步渲染?而且,即使在这个时期,通常也只有一名工程师负责所有的前端和后端工作。所以,现阶段只能算是半分离。
首先,这种方式的优点是显而易见的。前端不嵌入任何后端代码。前端专注于HTML、CSS、JS的开发,不依赖后端。还可以模拟Json数据来渲染页面。当您发现错误时,您可以快速识别谁有问题。
然而,这种架构仍然存在明显的缺点。最明显的如下:
正是因为上述缺点,我们迫切需要一个真正的前后端分离架构。
4、分离的时代
在前后端完全分离的这段时期,前端的范围被扩大,层也被认为是前端的一部分。在此期间:
但服务器人员不熟悉前端HTML结构,前端也不了解后端代码。图层如何实现?这就是node.js的妙用。 Node.js适合高并发、I/O密集、业务逻辑量小的场景。最重要的一点是前端不需要学习另外一种语言。对于前端来说,易用性大大提高。
你可以把它看成是一个与前端交互的API。总的来说,C的作用就相当于mvc中的C(控制器)。路由的实现逻辑是将前端静态页面代码以字符串的形式发送给客户端(如浏览器)。简单理解可以理解为,路由是提供给客户端的一组API接口,但返回的数据是一串页面代码。就这样。
用作连接服务器端 API 输出的 JSON 的桥梁。由于性能等原因,后端提供的接口返回的数据格式可能不适合前端直接使用。前端需要的排序、过滤功能,以及视图层的页面展示,可能都需要接口。提供的数据经过二次处理。虽然这些过程可以在前端执行,但是大量的数据可能会浪费浏览器性能。因此,现在添加Node中间层是一个很好的解决方案。
()不再直接请求JSP API,而是:
https://n.sinaimg.cn/spider20241024/87/w1080h607/20241024/8577-e75de92e770b8a7990b89a814e77d8e7.png
这样浏览器就得到了一个普通的HTML页面,而无需发送Ajax请求服务器。
淘宝前端团队提出的中途岛()的架构如下图所示:
添加node.js作为中间层具体有什么好处?
1、提高适应性;事实上,在开发过程中,我们经常会为PC端和App端开发一套前端。事实上,对于这三个终端来说,大多数终端的业务逻辑是相同的。唯一的区别是交互显示逻辑不同。
如果图层掌握在后端手中,而后端为了这些不同页面的显示逻辑而自己维护这些,那么模板就无法复用,只会增加与前端的通信成本。如果加上node.js层,架构图如下:
在这种结构下,各个前端的界面显示逻辑都由节点层自己维护。如果产品经理中途想改界面什么的,前端可以自己专职维护,后端不用操心。前端和后端各司其职。后端侧重于自身业务逻辑的开发,前端侧重于产品效果的开发。
2、提高响应速度;有时我们会遇到后端返回给前端的数据过于简单,前端需要对数据进行逻辑运算。那么当数据量比较小时,对其进行算术分组等操作就没有影响了。但当数据量较大时,就会出现明显的滞后效应。这时候节点中间层其实可以把很多这样的代码放到节点层去处理,也可以为后端分担一些简单的逻辑,并且可以使用模板引擎来控制前端的输出。这极大地提高了灵活性和响应能力。
3、性能得到提升;每个人都应该知道单一责任原则。从这个角度来说,当我们请求一个页面时,可能要响应很多后端接口。随着请求数量的增加,速度自然会变慢。这种现象到最后更加严重。使用node作为中间层,页面所需的多个后端数据在内网阶段直接组装起来,然后统一返回给前端,这样会带来更好的性能。
4、统一异步和模板;淘宝的主页是由数十个HTML片段组装而成(每个片段是一个文件)。以前PHP同步这几十个片段,必须是串行的。节点可以是异步的,读取文件可以是并行的。一旦这些片段也包含业务逻辑,异步的优势就变得显而易见。先渲染的文件将先输出并显示。
前端机的文件系统越复杂,页面组成的碎片越多,异步加速效果越明显。前后端模板的统一在无线领域非常有用。 PC页面和WIFI场景的页面适合前端渲染(后端数据Ajax到前端)。 2G、3G弱网环境适合后端渲染(数据随页面一起吐到前端),因此同一个模板在不同情况下使用不同的渲染通道,模板只需开发一次。
添加中间层后前后端职责划分:
5. 总结
从JSP++的经典MVC时代,到SSM()、SSH(++)的Java框架时代,再到前端框架(、、vueJS、)为主的MV*时代,再到领先的全栈时代,技术和架构总是在进步。虽然“基于 Node 的全栈开发”模式很令人兴奋,但要让基于 Node 的全栈开发变成稳定的、被大家接受的东西,还有很长的路要走。
创新之路不会停止。无论是前后端分离模式还是其他模式,都是为了更方便地解决需求,但它们只是一个“中转站”。前端项目和后端项目是两个项目,放在两台不同的服务器上,需要独立部署,两个不同的项目,两个不同的代码库,不同的开发人员。前端只需要关注页面的样式以及动态数据的解析和渲染,而后端则专注于具体的业务逻辑。
参考
正文结束
页:
[1]