参考链接:
https://zhuanlan.zhihu.com/p/54121733
本文作为笔记用,如有侵权,请联系删除。
1.JavaWeb三大组件
JavaWeb没有main,没有new,写一个类然后在web.xml中配个标签,程序就跑起来了。
简单来说就是“注入”和“回调”,
只要我们实现xxx接口,它会帮我们创建实例,然后搬运(接口注入)到它合适的位置,然后一套既定的流程下来,肯定会执行到。
Servlet接口实现的最难地方在于形参,然而Tomcat会事先把形参对象封装好传给程序员,除此之外,既不需要写TCP连接数据库,也不需要解析HTTP请求,更不需要把结果转成HTTP响应,request对象和response对象已经搞定了。我们写点业务逻辑就好了。
HTTP和Request/Response的关系就像菜园里的大白菜和餐桌上的酸辣白菜一样,HTTP请求到了Tomcat后,Tomcat通过字符串解析,把各个请求头(Header),请求地址(URL),请求参数(QueryString)都封装进了Request对象中。通过调用request.getHeader(); request.getUrl();request.getQueryString()可以得到浏览器当初发送的请求信息。
以上为GenericServlet的实现,是一个抽象类。
·提升了init方法中原本是形参的servletConfig对象的作用域(成员变量),方便其他方法使用
·init方法中还调用了一个init空参方法,如果我们希望在servlet创建时做一些什么初始化操作,可以继承GenericServlet后,覆盖init空参方法。
·由于其他方法内也可以使用servletConfig,于是写了一个getServletContext方法。
但没有实现service方法,果断放弃。
HttpServlet:它继承了GenericServlet。
一个类声明成抽象方法,一般有两个原因:
1.有抽象方法
2.没有抽象方法,但是不希望被实例化
HttpServlet做成抽象类,仅仅是为了不让new。(构造函数为空)
Filter用到了责任链模式,Listener用到了观察者模式,Servlet也不会放过使用设计模式的机会:模板方法模式。
如何写一个Servet?只需继承HttpServlet并重写doGet()/doPost()。
父类把能写的逻辑都写完,把不确定的业务代码抽成一个方法,调用它。当子类重写该方法,整个业务代码就活了。这就是模板方法模式。
2.我们为什么需要服务器?服务器最本质的作用有两个:
将资源对外暴露
配合各种传输协议进行响应输出
即使DNS解析域名得到对应的IP后,Request请求里还是会带上host。为什么?
因为:域名!=IP。
实际上一个IP可以对应多个域名。也就是说一台实体服务器(大铁柜),理论上可以有多个域名(虚拟主机)。实体服务器和网站是两个概念。IP只是对应实体服务器,而域名对应具体的网站。
比如上面百度服务器,虽然看起来115.239.210.27这个IP完全等同于http://www.baidu.com,但也有可能这个IP对应的服务器上配置了两个虚拟主机:www.baidu.com和tieba.baidu.com。所以即使找到了IP对应的服务器实体,Request请求还是要带上host主机名,以确定是哪个虚拟主机。
最后必须解释的是,上面的百度服务器只是举个例子,实际上百度搜索和百度贴吧的IP是不同的,也就是说它们不在同一台服务器上。通常来说,一个IP对应一台服务器,服务器上只有一个主机。拿到IP基本就可以确定要访问哪个网站。
3.3个容易混淆的小概念
(1)软件概念的服务器和硬件概念的服务器
软件概念上,只要是一台硬件配置正常、装有操作系统、插着电能上网,并且安装特定软件的电脑,都可以称为服务器。比如你要学习数据库了,于是你装了MySQL服务端,那么此时你的电脑就是一个MySQL服务器。然后你又装了SVN服务端,那么此时你的电脑既是MySQL服务器,又是SVN服务器。Tomcat服务器同理。
硬件概念上,服务器本质上也是一台电脑,只不过配置高的同时长相丑了点,基本就是一个冰冷的大铁柜。我们的笔记本电脑既能看电影又能玩游戏,而它们基本上专机专用。
(2)Web服务器?Web容器?
其实,Tomcat服务器 = Web服务器 + Servlet/JSP容器(Web容器)。
Web服务器的作用是接收客户端的请求,给客户端作出响应。但是很明显,服务器不止静态资源呀,所以客户端发起请求后,如果是动态资源,Web服务器不可能直接把它响应回去(比如JSP),因为浏览器只认识静态资源。所以对于JavaWeb程序而言,还需要JSP/Servlet容器,JSP/Servlet容器的基本功能是把动态资源转换成静态资源。我们JavaWeb工程师需要使用Web服务器和JSP/Servlet容器,而通常这两者会集于一身,比如Tomcat。
所以,我们用Java开发的Web应用只是一个半成品,类似于一个插件,而服务器则像一个收发器:
(3)什么是动态资源?
其实对于何谓动态资源,我也没有很精准的概念。要讲清楚一个东西是什么,有时是比较难的事。不如先说它不是什么。
首先,动态资源不等同于动态页面。所谓动态页面,就是页面会动,而会动的页面不一定是动态资源。比如我可以用JQuery执行一段代码,让一个Div不断放大缩小,但是很显然它还是一个HTML页面。
所谓动态资源,其实最显著的特征就是它能动态地生成HTML!比如JSP。动态资源有个“特色”:它的数据是“可拼装”的、而且“可以随时间变化”。下面用号称可以抗住8个明星同时出轨的新浪服务器举个例子:
把人名进行修改:
此时,粉丝们再次打开《花花世界》专栏,看到的就是:佟丽娅深夜买醉bravo。
上面这个例子很好地说明了动态资源(JSP)的两个特性:
可拼装:${name}"深夜买醉bravo"
随时间变化:刘亦菲→佟丽娅
那么为什么说HTML就是静态资源呢?我也可以修改HTML页面使它发生改变啊!很好,很有想法。那么请小编先学会Linux,然后远程连接服务器进入到Tomcat目录下修改吧。
动态资源和静态资源虽然都在服务器里,但是动态资源包含变量(“可拼装”特性),而变量维系着数据库和程序之间的联系。
如果把JSP比作电子广告牌,变量比作一根电线,而电线连接着一台电脑(数据库服务器)。那么只要电脑上重新编辑文本,广告牌的内容也会变,此谓动态。而静态资源就像一张布告,当初写什么就是什么,任他风吹雨打,都不会再改变了。
4.Tomcat架构
简略解释一下xml里的配置:
1.Server.xml文件中的配置结构和Tomcat的架构是一一对应的。根目录是<Server>,代表服务器,<Server>下面有且仅有1个<Service>,代表服务。
2.<Service>下有两个<Connector>,代表连接(需要的话可以再加)。
其实这个Connector就是我们在上面讨论百度服务器时画过的端口。大家可以看到Tomcat默认配置了两个端口,一个是HTTP/1.1协议的,一个是AJP/1.3协议(我也不知道是啥)。前者专门处理HTTP请求。
3.当我们在浏览器输入"http://localhost:8080/demo/index.html"时,浏览器是以HTTP协议发送的,当这个请求到了服务器后,会被识别为HTTP类型,于是服务器就找来专门处理HTTP的Connector,它的默认端口正是上门Server.xml配置的8080。
4.与Connector平级的还有个<Engine>(Tomcat引擎),也就是说<Service>有两个孩子,小儿子是<Connector>,大儿子是<Engine>。Connector的作用说穿了就是监听端口,如果用户访问地址是“localhost:8080/xx/xx”,那就由监听8080端口的Connector负责,如果是"https://www.baidu.com",那么就是443端口处理。其实Connector也不处理实际业务,它只是个孩子。但它会负责把客人(请求)带到哥哥Engine那,然后Engine会处理。
5.<Engine>下面有个Host,代表主机。
配置介绍到这里,要先停一下,讲个故事:
从前有个国家,叫The United States of Tomcat。
国王Service是个爱猫的人,家庭和谐美满。
他立了一个太子,叫做Engine。
另外还有还几个很小的儿子,不过都是亲王(Connector),未来可能还要再生几个Connector。
由于Tomcat国实在太小了,全城上下就几个人,所以亲王Connector们被派去守城门。
为了让太子得到锻炼,早日继承衣钵,国王Service告诉亲王儿子们:他国使者若来拜访,你们就带他去你们哥哥Engine那去,他会处理一切。
Engine贵为太子,有好几处府邸,比如HOST1,HOST2,未来可能再建几座府邸(新建虚拟主机),但是Engine说了,我一般都在localhost待着,来这找我便可。
每一座府邸里,都有好几个厢房(Context:我们开发的Web应用)。Engine会根据来访使者的通关文牒(localhost:8080/myWeb/index.html)安排他们去哪个房间(myWeb),拿什么礼品(index.html)。
我们每个动态web工程都有个web.xml,而conf里的这个,是它们的“老爹”。它里面的配置,如果动态web工程没有覆盖,就会被“继承”下来。我们会发现,conf/web.xml里配置了一个DefaultServlet:
总结一下Tomcat处理请求的几种方式: