我相信绝大多数程序员都是通过Hello World
开启了咱们的编程生涯,当年我看到这一句话在控制台显示时内心激动不已,仿佛我的代码带领我触及到了另一个世界。
跟“新世界”打了声招呼后便马不停蹄地学习了顺序、分支、循环,看着控制台循环显示出我定义好的文字,我认为这个"世界"尽就我手中!
紧接着再学习了数组、方法、面向对象、集合、I/O、多线程、网络编程、数据库……我有点迷茫了,我不知道这些知识能干嘛,于是照着网上做了几个XX管理系统。
正当我略有成就感时,别人的一句 “你这黑框框这么丑谁会用啊?” 把我所有自信都打没了。是啊,我自己做的这些小玩意连我自己都不会考虑使用,又哪能指望别人会用呢。
于是我开始思考如何才能做出大家愿意使用的程序,进而了解到原来编程还有众多方向:桌面端、移动端、游戏、Web等等等等,每一个方向都值得我们在其中深耕。因为当时我觉得一个网站能够轻而易举地被全世界的人访问和使用,这太帅了,刚好我会的Java非常适合做Web开发,所以我瞄准了Web开发方向。
要学习Web必然绕不开网页三剑客:HTML、CSS、JavaScript,通过它们我终于摆脱了黑乎乎的控制台!然而喜悦是短暂的,学了许久“三剑客”的我做出来的网页非常丑陋,和其它网站如云泥之别。并且我做出来的网页就是一些元素组装在那,只是通过一些操作变换一些元素,没有任何实际的功能(比如购物、看影视、搜索等等)!
我陷入了无尽的迷茫中,感觉我学了特别多的东西和知识,但完全不知道如何运用这些做出一个产品,一个让大家有使用欲望、有实际功能的产品。脑袋里各个知识点犹如孤立的零件,这些零件无法组装成一个机器,毫无意义。
我小小的脑袋里充满了大大的疑惑:
Java中的各个项技术有啥用,和网页有啥关系?
说Java适合做Web开发怎么半途又让我去学“网页三剑客”?
那些有实际功能的网页是怎么做出来?
我的网页为啥只能在本地看到,怎样才能让全世界的人看到?
……
当时这么多的迷茫险些让我放弃编程,出现这种情况并不全是因为技术有一定的上手门槛,更多是因为自己的学习方式有问题。我没有对将要学习的内容进行梳理和规划,而是一头扎进陌生领域的黑暗中,自然碰壁碰得头破血流。所以接下来在讲解具体代码前我们需要对Web开发进行一个简单的俯瞰,这样我们在学习技术的时候才能有的放矢、事半功倍。
世界是如何看到我们的网页
互联网的诞生让各计算机之间产生了联系,尽管最开始只有发发邮件等简单的功能,但这也让我们从孤岛走向了世界。那时我们数据的表现形式也非常简单,文字、图片、视频各司其职,要想使用这些数据必须打开相应的软件才行,比如最常用的txt
文本格式需要用记事本打开。随着时代的发展,人们开始不满足于如此单调的数据交互,超文本标记语言HTML应运而生。
为什么叫“超文本”呢,因为HTML所展示的内容不只是文字,它还可以展示链接、图片、视频、表格等多种数据:
表示链接;
表示图片;
表示视频;
表示表格;
……
上面一组组的尖括号就是HTML的标签,也可以叫元素。这些元素需要使用专门的软件才能正确渲染出对应的数据,否则和文本文字没有区别,这个渲染HTML的软件就是我们常说的浏览器。
只要在浏览器中输入正确的路径即可将HTML渲染成网页,这个路径可以是本地文件路径,也可以是网址。输入本地路径是将本计算机的HTML
文件直接打开然后渲染,输入网址则是从其他计算机上获取HTML内容然后进行渲染。这个给我们发送HTML的机器我们称为Web服务器。
如上图所示,从输入网址到渲染网页就两个流程:
从浏览器到服务器,这个流程称之为请求(Request);
从服务器到浏览器,这个流程称之为响应(Response);
虽然看上去非常简单,可这两个流程背后都包含了无数的细节。目前就有两个问题摆在我们面前:
一串网址而已,怎么就连接到了服务器?
服务器通过什么手段将HTML传输给浏览器?
我们就通过这两个问题作为切入点,来更加深入地剖析整个流程。
请求
URL和HTTP
网址大家都见过,比如http://www.rudecrab.com
。比起“网址”,这一串文字更精准的描述是URL(统一资源定位符)。为什么这么叫呢,因为这一串文字在全世界范围内需要保证唯一,以起到一个定位资源的作用,这个资源可以是一个HTML页面,可以是一张图片,也可以是其他东西。URL保证唯一是Web世界的重要前提,就好像手机号、身份证一样,如果有重复的可能则整个世界就要乱套了。
URL分为两个部分组成,协议和内容。要知道浏览器并不只有渲染网页这一个功能,不同的协议则代表不同的功能,浏览器根据协议来进行相应的操作!
HTTP协议全称为超文本传输协议(HyperText Transfer Protocol),浏览器和Web服务器之间按照该协议标准建立连接,从而传输数据。除了HTTP协议外还有许多协议,比如File协议则是用来打开本地文件,当你用浏览器打开本地网页时就可以看到文件路径前加上了file://
;FTP协议是用来上传/下载文件,等等。
协议用来确定功能,内容则是用来定位具体资源!www.rudecrab.com
相信大家都很熟悉,这就是我们常说的域名,它用来定位到具体的服务器。具体怎么定位,就是我们接下来要讲解的DNS技术了。
IP和DNS
服务器就是一台连接到互联网的计算机,在网络中所有的设备都会被分配一个地址用来作标识,这个地址就是IP地址。有了IP地址我们就可以确定通讯的发送方和接收方,两个设备间才可以互相通讯。
网络通讯全靠IP地址来进行定位,可这给我们带来了使用难度,浏览网页还要记得那么多数字这太麻烦了,所以就诞生了域名技术。我们直接输入域名就可以浏览网页,只不过在发送真正的HTTP请求前我们还需要将域名解析成IP地址,这个解析工作就是由域名系统DNS(Domain Name System)来完成的。
若把IP地址比作一个电话号码,那么域名就是联系人备注,而DNS就是一个通讯录! 当我们输入域名后,浏览器会向DNS服务器发送域名解析请求,DNS服务器中解析完毕之后则会将域名对应的Web服务器IP返回给浏览器。浏览器知道了IP后,才会发送真正的HTTP请求。这所有的工作浏览器在背后都帮我们做好了:
有人可能会问,那DNS服务器不也要靠IP来定位吗,浏览器又是怎么知道DNS服务器的IP呢?这是因为我们操作系统的网络配置中已经记录好DNS服务器的IP地址了,可以直接通过IP地址向DNS服务器发送请求。不同的操作系统查询本机的DNS地址方式不同,有兴趣的可以自行去查看了解。
还有人可能会问,为啥要多一道域名解析的工序呢,弃用IP直接用域名来作网络地址标识不好吗。这是因为IP地址的长度是固定的,而域名长度不是固定的,使用IP地址只需要处理4个字节的数据,而使用域名则可能需要处理几十上百个字节的数据,为了效率考虑就采用IP来进行网络寻址定位了。
响应
现在我们已经知道了当我们输入URL后浏览器是怎么连接到Web服务器,接下来我们就要搞懂服务器是怎样将HTML返回给浏览器!
软件和端口
服务器只是一台计算机一台硬件,收到网络请求后最终还是要由操作系统和程序软件去处理。硬件和操作系统太过底层,所以我们所说的处理网络请求一般都是讲的软件程序层面。这种提供了各种服务的程序,我们称为应用服务器。
这里要额外注意一点,我们常说的服务器、应用服务器、Web服务器往往都是一个概念,既可以指代硬件也可以指代软件。很多时候我们并不需要区分软硬件的语义,就好像我们常说的“我在用手机浏览网页”,此时手机的语义是硬件还是浏览器软件并不重要。我们根据上下文语境自然而然能提取出名词的含义,所以不需要纠结字眼,在需要区分语义的地方我会进行描述的。
应用服务器有很多种,除了Web服务器外还有FTP服务器、邮件服务器、数据库服务器,等等。一台计算机上可以安装多个服务器软件来同时提供服务,如果没有安装软件自然就没有对应的功能。IP地址是定位到硬件,那么当服务器收到请求的时候是如何判断要提供哪个服务呢?这时候就要用到端口(Port)。
ip地址就像是一个银行,端口就像是银行内的窗口,不同的窗口提供不同的服务。端口号的范围从0到65535,每个服务软件都有自己的端口,比如Web服务器默认的端口为80,FTP服务器默认的端口为21。当我们输入URL发起HTTP请求时,如果我们Web服务器的端口没有修改,默认端口80是可以省略输入的,如果我们端口修改了则需要指定端口才能成功发起请求:www.rudecrab.com:8080
。
静态网页和动态网页
现在我们知道了HTTP请求是交由Web服务器程序来处理,这个处理逻辑就是交由我们的代码来实现了!大家所说的Java适合做Web开发,就是指使用Java开发服务器程序!可以用来开发服务器程序的还有许多语言,比如PHP、Python、Go,等等,这些都可以统称为后端语言。这个后端就是指服务器、服务端;前端自然就是指浏览器、客户端,JavaScript就是前端语言。Web开发继续细分方向也就是:前端开发和后端开发。
Web服务器最基本的功能就是解析HTTP请求将HTML返回给前端,服务器上一般会存放多个文件,服务器要根据请求返回正确的文件。
直接输入域名rudecrab.com,后面不带目录或文件时,一般会默认返回根目录下的index.html。
收到请求数据为输入,返回响应数据为输出,所以只要有I/O(输入输出)的编程语言都可以完成此逻辑。我们固然可以通过语言的原生API来实现Web服务器,不过从零构建起来太过繁琐,业界已经有许多成熟的服务器程序供我们直接使用,如:Tomcat、Apache、Nginx,等等。我们只需安装这些程序,就可以处理HTTP请求并返回文件了!
这里就可以解答最开始的疑问:如何让世界看到我们的网页?首先要购买一台服务器,这个服务器不是说他邮寄一台主机给你,而是服务器厂商将设备连接到网络上,供你控制使用。然后我们在服务器上安装Web服务器程序,再将我们编写好的HTML文件上传到服务器上,别人就可以通过IP访问我们的网页了!如果想要让别人通过域名访问,那我们就还得购买一个域名,域名厂商都会提供DNS服务,我们只需将域名和服务器IP映射好即可。
既然有现成的Web服务器供我们安装使用,那我们学习的后端语言又有何用武之地呢?其实那些Web服务器只是帮我们做好了基础服务,具体的业务逻辑还是需要我们编写!每一个系统都有各自的业务特点,比如当用户输入账号密码传递到服务器,不同的系统都会做不同的业务处理;再比如我们每个系统都有不同的数据,这个数据存在数据库中也需要我们的服务器程序处理!
并且有很多网站,同一个URL,不同的用户看到的内容是不一样的,而且内容也会更新,这个内容动态变化的逻辑也是需要我们编写代码来控制!这种网页内容会根据不同的情况动态变换的网页叫做动态网页,反之,那些内容不会动态变换的网页就叫做静态网页。我刚开始听到动态网页这个词时,我还以为只要网页上有个动图就是动态网页呢,大家不要走进这个误区,像动图、元素动画这些只是“动态效果”,和我们所说的动态网页没有关系。
静态网页,就是我们之前图示的那样,将写好的HTML文件上传到服务器,服务器收到请求后直接将文件返回给客户端。除非我们修改了或重新上传了这个HTML文件,否则这个文件内容就一直不会变。
动态网页,是服务端收到请求后执行代码逻辑,动态生产一个HTML文件然后返回给客户端。
服务端渲染和客户端渲染
之前咱们说过Web开发细分为两个方向:前端开发和后端开发。那些漂亮的HTML页面和绚丽的交互效果就是前端负责的,具体的业务逻辑处理就是交由后端。有人可能会问,动态页面是在服务端通过后端代码生成的,没看到前端开发的影子呀?
其实,最开始并没有特地将前后端开发任务给分离开来,同一个开发人员除了编写业务逻辑外也要编写页面效果。随着业务要求和页面要求都越来越高,多种任务基于一身实在分身乏术,所以慢慢演变成页面效果交由前端开发人员编写,后端人员只需通过代码在HTML里填充内容就好了!这种前后端的拆分只是开发任务的拆分,最终的HTML页面还是在后端生成并返回的,也就是说一台Web服务器要执行业务代码也要生成页面,这对于服务器来说压力太大了,并且业务逻辑和HTML页面终究是混合在一块的,不方便管理和维护。为了解决这个问题,动态生成HTML页面的任务开始从服务器端剥离,变成客户端渲染,即现在流行的前后端分离开发模式!
服务端渲染是指服务端生成完整的HTML页面然后返回给客户端,客户端只需要解析HTML即可。
客户端渲染是指服务器只返回包含了一些简单元素的静态的HTML页面,由客户端通过JavaScript来填充内容。
前后端分离模式下,前端开发人员只需关注交互效果,后端开发人员只需关注业务逻辑,开发效率非常高。咱们在学习的时候也得确认好自己的方向,前端和后端都有非常庞大的体系需要我们去钻研,当然,能力够了的情况下可以两者兼顾,即全栈开发!
无论选择哪一个方向都不能一叶障目,作为后端开发人员也要了解一些前端的知识,如果对前端一窍不通那你都无法理解交互逻辑、数据扭转,又谈何业务逻辑的编写呢,这也是我们学习Java的过程中要去学习前端的原因。
俯瞰
经过一番梳理后我相信咱们对Web已有了一个大概脉络,方便咱们在学习的时候明确自己的学习方向。当然,这只是做了一个简单的梳理,有许多细节没有讲到,比如TCP/IP协议、HTTP报文、CDN,等等。不过刚开始只需理解一个大概轮廓即可,不然容易陷入细节的风暴中绕不出来了!
后面我会陆续补充更多的细节,从单机应用演进到分布式微服务架构,由浅入深咱们慢慢来!
博客、Github、微信公众号请认准:RudeCrab,欢迎关注!如果对你有帮助可以收藏、点赞、star、在看、分享~~ 你的支持,就是我写文的最大动力
微信上转载请联系公众号开启白名单,其他地方转载请标明原地址、原作者!