本文链接 | www.cnblogs.com/xuange306
以前的项目大多数都是 Java 程序猿又当爹又当妈,既搞前,又搞后端。
随着时代的发展,渐渐的许多大中小公司开始把前后端的界限分的越来越明确,前端工程师只负责前端的事情,后端工程师只管后端的事情。正所谓术业有专攻,一个人如果什么都会,那么每一样都很难达到精通。
大中型公司需要专业人才,小公司需要全才,但是对于个人职业发展来说,选定一个方向,坚持走下去,就对了。
例如你打算专注于 Java 后端,那么把你的精力专注在 Java,JVM 原理,Spring 原理,MySQL 锁,事务,多线程,大并发,分布式架构,微服务,以及相关的项目管理等等,这样你的核心竞争力才会越来越高,正所谓你往生活中投入什么,生活就会反馈给你什么。
我们的 Java Web 项目都是使用了若干后台框架进行开发,Spring、Spring MVC、MyBatis、Hibernate 等等。
而且大多数项目在 Java 后端都是分了三层,控制层、业务层、持久层。控制层负责接收参数,调用相关业务层,封装数据,以及路由到 JSP 页面。然后 Jsp 页面上使用各种标签(jstl/el)表达式将后台的数据展现出来。
我们先看上述这种情况,需求定完了,代码写完了,测试测完了,然后发布:
你需要用 Maven 或者 Eclipse 等工具把你的代码打成一个 war 包,然后把这个 war 包发布到你的生产环境下的 Web 容器里,发布完了之后,你要启动你的 Web 容器,开始提供服务,这时候你通过配置域名,dns 等等相关,你的网站就可以访问了。
那我们来看,你的前后端代码是不是全都在那个 war 包里?包括你的 js,css,图片,各种第三方的库,对吧?
好,下面在浏览器中输入你的网站域名:www.xxx.com,之后发生了什么?
浏览器在通过 ip 路由到你的服务,在 tcp3 次握手之后,通过 tcp 协议开始访问你的 Web 服务器,你的 Web 服务器得到请求后,开始提供服务,接收请求,之后通过 response 返回你的应答给浏览器。
我们先假设你的首页中有 100 张图片,以及一个单表的查询,此时,用户的看似一次 http 请求,其实并不是一次,用户在第一次访问的时候,浏览器中不会有缓存,你的 100 张图片,浏览器要连着请求 100 次 http 请求(有人会跟我说 http 长链短链的问题,不在这里讨论),你的 Web 服务器接收这些请求,都需要耗费内存去创建 socket 来玩 tcp 传输。推荐阅读: 40 篇原创干货,带你进入 Spring Boot 殿堂!
重点来了,这样的话,你的 Web 服务器的压力会非常大,因为页面中的所有请求都是只请求到你这台服务器上,如果 1 个人还好,如果 10000 个人并发访问呢(先不聊 web 服务器集群,这里就说是单实例 Web 服务器),那你的服务器能扛住多少个 tcp 链接?你的服务器的内存有多大?你能抗住多少 IO ?你给 web 服务器分的内存有多大?会不会宕机?
这就是为什么,越是大中型的 Web 应用,他们越是要解耦。
理论上你可以把你的数据库+应用服务+消息队列+缓存+用户上传的文件+日志+等等都扔在一台主机上,但是这样就好像是你把鸡蛋都放在一个篮子里,隐患非常大。
正常的分布式架构,是都要拆开的,你的应用服务器集群(前,后)+文件服务器集群+数据库服务器集群+消息队列集群+缓存集群等等。 推荐阅读 : 40 篇原创干货,带你进入 Spring Boot 殿堂!
下面步入正题,首先以后的 Java Web 项目都尽量要避免使用 JSP,要搞前后端解耦,玩分布式架构,这样我们的应用架构才更强。
动态资源和静态资源全部耦合在一起,无法做到真正的动静分离。服务器压力大,因为服务器会收到各种 http 请求,例如 css 的 http 请求、 js 的、图片的、动态代码的等等。一旦服务器出现状况,前后台一起玩完,用户体验极差。
前端工程师做好 html 后,需要由 Java 工程师来将 html 修改成 jsp 页面,出错率较高(因为页面中经常会出现大量的 js 代码),修改问题时需要双方协同开发,效率低下。
JSP 必须要在支持 Servlet 的 Web 服务器里运行(例如 tomcat 等),无法使用 nginx 等(nginx 据说单实例 http 并发高达 5w,这个优势要用上),性能提不上来。
第一次请请求 JSP,必须要在 Web 服务器中编译成 Servlet,第一次运行会较慢。
每次请求 JSP 都是访问 Servlet 再用输出流输出的 html 页面,效率没有直接使用 html 高。
JSP 内有较多标签和表达式,前端工程师在修改页面时会捉襟见肘,遇到很多痛点。
如果 JSP 中的内容很多,页面响应会很慢,因为是同步加载。
基于上述的一些痛点,我们应该把整个项目的开发权重往前移,实现前后端真正的解耦!
客户端请求
服务端的 Servlet 或 Controller 接收请求(路由规则由后端制定,整个项目开发的权重大部分在后端)
调用 Service,dao 代码完成业务逻辑
返回 JSP
jsp 展现一些动态的代码
浏览器发送请求
直接到达 html 页面(路由规则由前端制定,整个项目开发的权重前移)
html 页面负责调用服务端接口产生数据(通过 ajax 等等)
填充 html,展现动态效果。
有兴趣的童鞋可以访问一下阿里巴巴等大型网站,然后按一下 F12,监控一下你刷新一次页面,他的 http 是怎么玩的,大多数都是单独请求后台数据,使用 json 传输数据,而不是一个大而全的 http 请求把整个页面包括动+静全部返回过来。 推荐阅读 : 40 篇原创干货,带你进入 Spring Boot 殿堂!
可以实现真正的前后端解耦,前端服务器使用nginx。
前端服务器放的是 css,js,图片等等一系列静态资源。甚至你还可以 css,js,图片等资源放到特定的文件服务器,例如阿里云的 oss,并使用 cdn 加速,前端服务器负责控制页面引用,跳转,调用后端的接口,后端服务器使用 tomcat 。
这里需要使用一些前端工程化的框架比如 nodejs,react,router,react,redux,webpack。
发现 bug,可以快速定位是谁的问题,不会出现互相踢皮球的现象。
页面逻辑,跳转错误,浏览器兼容性问题,脚本错误,页面样式等问题,全部由前端工程师来负责。
接口数据出错,数据没有提交成功,应答超时等问题,全部由后端工程师来解决。
双方互不干扰,前端与后端是相亲相爱的一家人。
在大并发情况下,我可以同时水平扩展前后端服务器,比如淘宝的一个首页就需要 2000 台前端服务器做集群来抗住日均多少亿+的日均 pv。
去参加阿里的技术峰会,听他们说他们的 Web 容器都是自己写的,就算他单实例抗 10 万 http 并发,2000 台是 2 亿 http 并发,并且他们还可以根据预知洪峰来无限拓展,很恐怖,就一个首页。
减少后端服务器的并发压力,除了接口以外的其他所有 http 请求全部转移到前端 nginx 上。
即使后端服务暂时超时或者宕机了,前端页面也会正常访问,只不过数据刷不出来而已。
也许你也需要有微信相关的轻应用,那样你的接口完全可以共用,如果也有 app 相关的服务,那么只要通过一些代码重构,也可以大量复用接口,提升效率。
页面显示的东西再多也不怕,因为是异步加载。
在开需求会议的时候,前后端工程师必须全部参加,并且需要制定好接口文档,后端工程师要写好测试用例,不要让前端工程师充当你的组专职测试,推荐使用 Chrome 的插件 Postman,Service 层的测试用例拿 junit 写。
上述的接口并不是 Java 里的 interface,说白了调用接口就是调用你 Controler 里的方法。
加重了前端团队的工作量,减轻了后端团队的工作量,提高了性能和可扩展性。
我们需要一些前端的框架来解决类似于页面嵌套,分页,页面跳转控制等功能。(上面提到的那些前端框架)。
如果你的项目很小,或者是一个单纯的内网项目,那你大可放心,不用任何架构而言,但是如果你的项目是外网项目,呵呵哒。
以前还有人在使用类似于 velocity/freemarker 等模板框架来生成静态页面,现在这种做法也被淘汰掉了。
这篇文章主要的目的是说 JSP 在大型外网 Java Web 项目中被淘汰掉,可没说 JSP 可以完全不学,对于一些学生朋友来说,Servlet 等相关的 Java Web 基础还是要掌握牢的,不然你以为 Spring MVC 这种框架是基于什么来写的?
1、 一键部署 Spring Boot 到远程 Docker 容器,就是这么秀!
2、 完结撒花!129 集 21 个小时,松哥自制的 Spring Boot2 系列视频教程杀青啦!
3、 40 篇原创干货,带你进入 Spring Boot 殿堂!
4、 Spring Boot 中的同一个 Bug,竟然把我坑了两次!
5、 Spring Boot 支持 Https 有那么难吗?
6、 一个野生程序员的自我修养
7、 干货 | 鸟瞰 MySQL,唬住面试官!
8、 Spring Boot 修改静态资源一定要重启项目才会生效吗?未必!
9、 Spring Boot 跨域,JSONP 太 low,试试 CORS 怎么样?
喜欢就点个 "在看" 呗^_^