作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
本篇开始,我们正式进入JavaWeb章节的学习。
JavaWeb阶段的学习秉持着"先松后紧、概念先行"的策略,注重帮大家理清web开发的一些概念和细节,并辅以必要的代码和案例,期望帮大家扫清犄角旮旯的一些盲点。
文章风格照旧,我们坚持实用、打好基础,以另类的角度重新复习一遍大家习以为常的知识点。
Tomcat学艺
Tomcat,熟悉的陌生人。我们所有的项目都运行在它上面,而我们却往往对它视而不见。现实中也是如此,我们周围充满了空气,我们无时无刻不在呼吸,但你从来没关心过它。同样的,Tomcat于我们而言,也只是在创建环境或者运行项目爆出各种错误时,才会去看看它。
上世纪90年代在大洋彼岸,有一家名唤SUN的公司,创造了一门全新的语言,叫Java。经过短短几年的发展,一跃成为市场上最炙手可热的语言。随后又悟出"Java13绝技",也就是所谓的JavaEE规范:JDBC,JNDI,EJB,RMI,JSP,Servlets,XML,JMS,Java IDL,JTS,JTA,JavaMail,JAF。
在大洋彼岸还有一家公司,准确来说它是一个组织,专门搞开源的,叫Apache。这家公司搞出了一个叫Tomcat的服务器。这个名字取得真好啊。中国有个词叫三脚猫,专门来吐槽别人功夫不到家。巧了,Tomcat也没完全实现JavaEE规范。13种核心技术,Tomcat只实现了俩:Servlet和JSP。而其他服务器比如JBoss、Weblogic啥的都是完全支持的。所以人们往往更愿意叫Tomcat为轻量级的服务器,也有叫它Servlet/JSP容器的。
听到这,你不禁大叫:不对啊,我记得自己写的程序里有用到JDBC啊,还可以运行哩!
啊,那是因为你导了JDBC包...但是你安装了Tomcat后另外导过Servlet/JSP的包吗?没有嘛!人家实现了Servlet/JSP规范,都整到自己源码里了。
说到这,我也是泪流满面。因为我才发现自己也是个三脚猫。上面"Java13绝技"我特么也就学过JDBC/XML/JSP/Servlet...所以我更愿意称自己是JavaWeb程序员,而不是JavaEE程序员。
我们为什么需要服务器?
在我看来,服务器最本质的作用有两个:
- 将资源对外暴露
- 配合各种传输协议进行响应输出
假设现在有个问题:
给你两台电脑,不通过蓝牙/QQ/微信,也不通过网盘或USB等可移动设备做中介,你要如何把一张图片从一台电脑传到另一台?
听到这个问题,我估计大部分非科班的朋友都要懵。因为如果后期没有刻意去学习计算机网络,我们对于网络的了解基本仅限于基础班4小时的"网络编程"讲解。而大家平时又太习惯地址栏键入"www.baidu.com",无脑一回车就上网冲浪了。现在突然让你去访问隔壁的电脑,确实有点束手无策。
解决这个问题的方法可能有多种,这里介绍其中一种:通过服务器访问。
请先了解以下三个概念:
- IP:电子设备(计算机)在网络中的唯一标识,一个IP对应一台实体电脑
- 端口:应用程序在计算机中的唯一标识,一个端口只能被唯一程序占用
- 传输协议:数据传输的规则
中国有14亿人口,每个人都有唯一的身份标识:身份证,用以精确定位某个个体。同样的,网络上有几十亿台电脑,每台电脑都有自己的一串特有IP(不同局域网内可以相同),也就是说一个IP代表一台特定的实体电脑。比如《唐伯虎点秋香》中华安的编号是9527,而华府的管家从不叫他名字,而是直接喊"9527"。因为"9527"就是华安。
虽然根据IP可以精准定位一台电脑,但是还不足以让我们访问这台电脑。就好比你知道了我的门牌号,但是我没给你开门。所谓的门,就是一个端口,而端口的背后是应用程序。
一般来说,一个端口可以定位一个软件,但一个软件可以占用多个端口(你家的门,只属于你家,但可以有前后门)。在现实生活中,你家的门如果被别人占用了或者堵了,客人(请求)就进不去了。而在程序中,如果有两个程序的端口相同,就会发生端口冲突,也就是所谓的"端口占用"。端口占用的后果往往是程序无法启动,更遑论运行。
关于端口,再举个例子:
微信和QQ都是腾讯公司的,你的电脑上同时装了这两个软件。为什么我用QQ给你发消息,你的微信收不到?
正常人看起来很傻的问题,实际上并不是那么简单。
每个应用程序都有自己的端口号(可能有多个),它们一旦运行,就要去监听这些端口。每个程序都是电脑的囚犯,看不到外面的世界,而端口就是给这些囚犯送饭的窗口。应用程序们整天躲在电脑里盯着自己的端口们,祈求着别的计算机来访时能送个大鸡腿(Request请求)。
其实QQ这些软件属于C/S架构,已经为我们屏蔽了太多底层,什么IP、端口全部都是自动封装的。相比来说,B/S架构更直观一些。比如用浏览器访问百度:
想要访问一台服务器,必须知道它的IP。但我们人类不擅长记忆长串数字,于是人类搞了所谓的域名来指向IP。但实际请求时,最终还是要换算成IP去访问。总得来说有两种换算的途径:
- 本机的hosts文件
- DNS服务器
不知道有没有细心的朋友注意到了下面的细节:
即使DNS解析域名得到对应的IP后,Request请求里还是会带上host。为什么?
因为:域名!=IP。
实际上一个IP可以对应多个域名。也就是说一台实体服务器(大铁柜) ,理论上可以有多个域名(虚拟主机)。 实体服务器和网站是两个概念。IP只是对应实体服务器,而域名对应具体的网站。
比如上面百度服务器,虽然看起来115.239.210.27这个IP完全等同于.baidu.com,但也有可能这个IP对应的服务器上配置了两个虚拟主机:www.baidu.com和tieba.baidu.com。所以即使找到了IP对应的服务器实体,Request请求还是要带上host主机名,以确定是哪个虚拟主机。
通过DNS解析域名得到IP,然后根据IP+host找到服务器
另外,如果两个域名对应同一个IP,那么必须设置其中一个域名为默认的,不然同一台服务器有两个虚拟主机,我该访问谁?
已经知道IP,就无需DNS解析,可直接访问服务器。若这个IP对应的服务器有两个虚拟主机,而用户Request请求行中又没有指定host,则会访问默认主机(因此服务器要事先指定默认主机!Tomcat默认localhost)
最后,再用Tomcat举个例子。比如,现在我有一台笔记本电脑(一个实体服务器),它的本机IP是192.168.112.1,我在上面装了Tomcat。如果Tomcat不改动配置,则默认只有一个虚拟主机localhost(默认主机)。接着我开发了一个JavaWeb程序demo1部署到Tomcat,然后我同事在浏览器输入下方地址:
192.168.112.1:8080/demo1/index.html
访问我的电脑。虽然没有带host,但是localhost是默认的,于是访问它。
不过,上面的百度服务器只是举个例子,实际上百度搜索和百度贴吧的IP是不同的,也就是说它们不在同一台服务器上。通常来说,一个IP对应一台服务器,服务器上只有一个主机,拿到IP基本就可以确定要访问哪个网站。
3个容易混淆的小概念
我们经常开口闭口"服务器"、"服务器"的,其实"服务器"是个很容易引发歧义的概念,我能想到的就有3点:
- 软件概念的服务器和硬件概念的服务器
- Web服务器?Web容器?
- 我们开发的Web应用都是半成品!
软件概念的服务器和硬件概念的服务器
软件概念上,只要是一台硬件配置正常、装有操作系统、插着电能上网,并且安装特定软件的电脑,都可以称为服务器。比如你要学习数据库了,于是你装了MySQL服务端,那么此时你的电脑就是一个MySQL服务器。然后你又装了SVN服务端,那么此时你的电脑既是MySQL服务器,又是SVN服务器。Tomcat服务器同理。
硬件概念上,服务器本质上也是一台电脑,只不过配置高的同时长相丑了点,基本就是一个冰冷的大铁柜。我们的笔记本电脑既能看片又能玩游戏,而它们基本上专机专用。
Web服务器?Web容器?
其实,Tomcat服务器 = Web服务器 + Servlet/JSP容器(Web容器)。
Web服务器的作用是接收客户端的请求,给客户端作出响应。但是很明显,服务器不止静态资源呀,所以客户端发起请求后,如果是动态资源,Web服务器不可能直接把它响应回去(比如JSP),因为浏览器只认识静态资源。所以对于JavaWeb程序而言,还需要JSP/Servlet容器,**JSP/Servlet容器的基本功能是把动态资源转换成静态资源。**我们JavaWeb工程师需要使用Web服务器和JSP/Servlet容器,而通常这两者会集于一身,比如Tomcat。
Web服务器接收、响应客户端请求,Web容器装载Servlet/JSP,让它们去处理动态资源
所以刚才我们画的百度服务器,其实细节还可以更丰满些:
我们开发的Web应用都是半成品!
我们写代码的时候,都知道相同代码最好抽取成公共方法以复用。现在我们来想一想,上百上千的Web应用有什么共性吗?
首先,资源肯定不同,无法抽取。比如优酷主打视频,知乎基本都是文字。
其次,业务也肯定不同,比如百度主要是搜索,淘宝是电商。但是有一点是一样的,这些网站都需要"接收用户请求"+"响应用户请求"。
嗯?桥多麻袋!!这两个概念,好像哪里见过!不错,就是上面的Web服务器。仔细回想一下,我们开发JavaWeb时,你操心过如何接收HTTP请求和响应HTTP请求吗?显然没有嘛!因为你一直忙着debug。所以,我们用Java开发的Web应用只是一个半成品,类似于一个插件,而服务器则像一个收发器:
什么是动态资源?
其实对于何谓动态资源,我也没有很精准的概念。要讲清楚一个东西是什么,有时是比较难的事。不如先说它不是什么。
**动态资源不等同于动态页面。**所谓动态页面,就是页面会动,而会动的页面不一定是动态资源。比如我可以用JQuery执行一段代码,让一个Div不断放大缩小,但是很显然它还是一个HTML页面。
**所谓动态资源,其实最显著的特征就是它能动态地生成HTML!**比如JSP。动态资源有个"特色":它的数据是"可拼装"的、而且"可以随时间变化"。下面用号称可以抗住8个明星同时出轨的新浪服务器举个例子:
突然,新浪《花花世界》专栏的小编发现,原来和smart哥有绯闻的不是刘亦菲,而是佟丽娅,于是打开专栏做了修改:
此时,粉丝们再次打开《花花世界》专栏,看到的就是:佟丽娅深夜买醉smart哥。
上面这个例子很好地说明了动态资源(JSP)的两个特性:
- 可拼装:${name}"深夜买醉smart哥"
- 随时间变化:刘亦菲→佟丽娅
那么为什么说HTML就是静态资源呢?我也可以修改HTML页面使它发生改变啊!很好,很有想法。那么请小编先学会Linux,然后远程连接服务器进入到Tomcat目录下修改吧。
动态资源和静态资源虽然都在服务器里,但是动态资源包含变量("可拼装"特性),而变量维系着数据库和程序之间的联系。
如果把JSP比作电子广告牌,变量比作一根电线,而电线连接着一台电脑(数据库服务器)。那么只要电脑上重新编辑文本,广告牌的内容也会变,此谓动态。而静态资源就像一张布告,当初写什么就是什么,任他风吹雨打,都不会再改变了。
动手实现"Tomcat"
最后,还有个很无聊的问题留给大家思考:JavaSE阶段,我们无论做什么,都是上来先敲main()。学了JavaWeb后,我想问问,你有多久没敲main()了?她去哪了呢?
来找smart哥要视频!
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
进群,大家一起学习,一起进步,一起对抗互联网寒冬