从JSP的发展历程谈谈前后端分离
最近工作里写前端写得很是快(yu)乐(men),每次在浏览器调试JS,CSS的时候就会想为什么我一个后端要去做改界面的工作。当然了其实在以往web应用还不是很庞大的时候,后端程序员都是既当爹又当妈的,根本不需要什么分布式,前端也不需要做工程化:只要UI改好静态页面(html),你后端自己拿去爱干什么干什么,后面的事情包括js都跟我无关(第一个实习公司就是这么干的,估计很多维护旧项目的团队也都是这么干的)。
好了回到正题,我们研究JSP的发展,从JSP的诞生以及它的兴衰,再到前端框架的出现,可以大概窥探前端展示的发展历程,从而探讨前后端分离。
JSP的诞生
一样工具的诞生,往往是因为人们对这方面有需求。JSP的诞生在早期的java web时代,它的诞生与另一个远古巨兽servlet有关(这些东西对于我们这种95后肯定是接触得非常少的,但是它却是现今各种后端框架的基础)。在没有jsp之前,那真是刀耕火种的年代。如果需要返回一个页面,程序猿需要一行行print,需要插入变量的地方还需要自己拼凑字符串:
上进的程序员当然都不想做这种又苦又累又没有技术的事情,于是不知道哪个家伙发明了jsp,它的本质也是servlet,但是却可以让你编写一个Jsp就像编写html一样简单,不同的是它可以在html标签‘<%%>’中嵌入java代码!这就允许你在html中使用变量,使用java语言插入动态的内容。而最后通过把jsp编译成servlet,最后jsp就和servlet殊途同归了,但是却给程序员开发提供了极大的便利。
JSP的发展
JSP诞生之后,程序员写页面写得爽,所有业务逻辑、页面展示逻辑都往JSP塞,最后JSP扛不住了,程序员也扛不住了:页面非常凌乱,Html标签和java代码随处混合在一起,一个jsp页面非常长,甚至达到上千行代码,亟待程序员帮它减肥。
展示逻辑(视图)和业务逻辑(控制器)混合在一起,你想到了什么?对,就是MVC。后来人们又充分地利用了servlet和jsp这对兄弟,使用Jsp做页面展示,使用servlet处理后台的业务逻辑,利用起MVC来拆分原本臃肿的JSP。
这样处理后,JSP就不处理业务逻辑了,代码量减少了很多,瘦身成功。但是还有一些小问题,JSP想要获取servlet的变量,还是需要在’<%%>’这东西中通过java代码去获取。有些比较复杂的展示逻辑如循环for、条件if,还是需要在’<%%>’中编写java代码。我们希望是尽量不要在视图中写java代码。于是有人就封装了一层,出现了EL表达式和JSTL标签库:使用EL表达式取值,使用JSTL来处理页面展示逻辑。
${names}就是EL的取值表达式,而、就是JSTL标签了,这样就差不多可以把JSP的java代码都去掉了,页面展示清爽了。
JSP受到的威胁
虽然出现了EL和JSTL,但是还是有些程序员会忍不住直接在JSP中写java代码。后来就出现了Freemarker和Velocity等模板引擎,程序员完全无法里面写java代码了,其他都跟jsp差不多,通过标签来负责展示逻辑。另外模板引擎还可以脱离web容器使用,这是jsp无法做到的。就我在工作中遇到过的,有使用它们来生成邮件模板的,有使用它们来做代码生成器的。
模板引擎出现后,JSP损失了部分用户。
前端的崛起
在以往的项目中,前端都只是一个附属,在整个开发中地位并不高,毕竟它们改好的页面还需要交给后端人员去进行大量的修改(把html修改成jsp,使用JSTL标签使其变成动态的页面),最后可能改到前端自己本身也不认得这个页面是他做的。整个开发中重点都在后端人员身上,这可能是如今鄙视链产生的历史原因:后端认为所有有技术难度的都是我做的,你前端不过是一个切图的罢了。
但是随着项目越来越庞大,像淘宝这种电商网站,可能有成千上万的页面,页面的逻辑也是越来越复杂,高傲的后端再也玩不下去,希望前端可以帮他们分担工作。
前端终于找到翻身的机会了,他们抛弃了后端的那一套,请Javascript来自己造了一套(要知道,js到了浏览器就是王,是真的可以为所欲为的),并且要求后端只管数据接口,提供HTTP接口给前端(说白了就是类似SpringMVC的controller),让前端负责去请求数据并展示。来看看他们具体做了什么:
页面上放弃了JSP,只使用简单的Html、CSS负责展示,那如果想要展示动态的内容怎么办?使用js。一般的做法就是使用ajax请求json数据,然后前端把请求到的数据填充、渲染出来。但是!不要以为前端会直接使用js操作DOM。他们也有框架,他们甚至把MVC搬到了前端,Angular就是这样做的。
Angular使用js作为控制器,html作为视图,在js中异步去请求数据,然后html使用Angular标签来负责展示逻辑(就像JSTL、EL一样),把请求到的数据填充到html中,可以避免去直接操纵DOM,想想以前人们直接在DOM中查找元素、更新元素就觉得蛋疼了。
从此,前后端各立门户,各建工程,分了前端工程和后端工程(对了前端也做工程化,也需要打包、测试、部署),只要约定好数据接口,大家在需求开发时可以并行开发,各司其职。展示有问题找前端,数据有问题找后端。
架构上的改变
以前的做法是所有动态、静态资源都打包成一个war包,部署到tomcat中,单机部署,单机提供服务,这对于以往一些流量不大的网站或者一些内部系统来讲,这种做法完全足够了。但是如今互联网性能要求越来越高,单点是不可能满足高性能,高并发,高可用的要求的。
现在的做法是静态资源全部部署到nginx中,动态资源放在tomcat中,也就是动静分离的思想。一个请求过来,先请求nginx的静态资源,浏览器加载静态资源后,通过nginx的反向代理请求后端服务器,这里还可以使用nginx的负载均衡,添加多台后端服务器:
这样,html页面+json渲染 == 最终展示在用户面前的页面。
tomcat和nginx区别:
nginx是Http服务器,专为处理Http请求而诞生,处理Http请求能力强,适合用于处理静态资源(通过Http请求如实地返回内容,并且每个请求处理时间不会很长),底层采用单线程异步非阻塞方式,当读取静态资源发生IO时,可以先处理其他请求。据说nginx单机能抗5W并发。
tomcat是servlet/JSP容器,就是servlet/JSP运行的环境,tomcat把接收到的http请求交给servlet处理,然后servlet处理那些不讲逻辑的业务逻辑,适合处理动态资源。tomcat一般采用线程池的方式处理请求,当请求数量多,线程处理时间长,线程处理不过来,线程间会频繁切换,消耗大量cpu资源和内存。当请求超过一定的数量,会拒绝连接。因此JSP并不适合用于高并发的场景。
(完)
新开了个微信公众号,文章会第一时间发布到此公众号,欢迎关注