你确定你了解Tomcat吗(一)?

各位看官老爷大家好,我又写完了一篇枯燥且无味的博客,火速前来发布

Tomcat

身为一个整天和web打交道java码农,Tomcat是我们整天抬头不见低头见的好朋友,好工具, 但是好朋友要做到互相了解,所以,这篇文章帮你了解Tomcat,做他的好朋友,这样,下次它不高兴报错的时候我们也可以对症下药…
我们平时用框架开发出的java后端程序,部署到Tomcat中才可以发挥它的作用,所以,Tomcat其实是一个本地服务,我们将我们的java程序放入其中,然后启动Tomcat服务,其他电脑就可以通过网络访问我们的tomcat,来访问我们的程序。

接下来请大家坐稳扶好,前往tomcat底层架构的列车即将启动......

在我们学习tomcat的时候,可能最常听到的就是tomcat是一个servlet容器, 如果要我们用代码写的话,可能就是这个样子的

class Tomcat{
	List<Servlet> servlets;
}


如图所示(如果看不懂这个的客官老爷出门左转不送),这是一个简单的servlet,我们都知道,servlet是tomcat用来处理我们的请求的,那么它是如何处理我们的请求的呢?肯定有看官老爷就要说了,调用doGet方法呀!
对,确实是这样,但是我们在调用方法时,一般是这样的

IServlet servlet = new IServlet();
servlet.doGet(request, response);

于是,我们会有这样一个疑问,在tomcat中,这个doGet方法的调用是不是形如这个样子呢?还有,当我们ctrl + 左键点入HttpServletRequest的源码的时候,我们会发现它是一个接口,同样,HttpServletResponse也是一个接口,那么,我们就又有一个疑问了,当我们调用doGet方法的时候,传入的HttpServletRequest或者是HttpServletResponse类型的实际对象是什么呢?

这时,有观众老爷就要说了,妈的,少给老子卖关子,小心改日登门拜访

别激动,别激动…其实我们的这两个接口的实现类是由其对应的容器进行实现的,就是说,如果你将应用程序部署到tomcat,就是tomcat给我们进行实现,如果部署到jetty的话,就是jetty给我们进行实现的。可以这么理解,我们的这两个接口其实是HttpServlet的规范,我们的容器对这个接口的实现类,就相当于是对这个规范的实现。
那么,这两个接口在tomcat中的实现类是什么呢?

RequestFacade req = (RequestFacade) request;

如果大家在上面那张图的基础上,将这句代码加到打印输出的上面,会发现程序运行后,是可以正常打印出结果的,看到这里,各位看官老爷是不是明白了什么羞羞的东西呢?

tomcat在实现RequestFacade的时候,其实并不是将HttpServletRequest中的方法在这个类中都进行了实现,它是调用了它内部的一个叫做Request request的一个属性,所有具体的实现在这个Request类中,而RequestFacade这个类就像它的名字一样,是tomcat用来暴露给外面的人使用的,所以说,当tomcat处理完请求的时候,生成的是一个Request类。
所以说Request是一个核心类,而RequestFacade是Tomcat的一个用于实现HttpServlet约束的一个门面类。

Tomcat中的容器类

在tomcat中有四个类继承了Container容器类, 分别是Context, Wrapper, Host, Engine, 它们分别是做什么的呢?
Context就像上边说的,他代表的是我们的应用程序,我们的每一个应用程序都是一个Context.
Host代表了我们的虚拟主机, 它包括了Context,我们通常在url中写的localhost就是一个默认的虚拟主机,我们还可以自定义配置其他的虚拟主机,在server.xml文件中进行配置即可
Engine就好像是一个集群,它包括的很多虚拟主机
Wrapper: 当我们的servlet不是单例模式的时候,wrapper就是管理同一个servlet类型的不同实例, 假如说我有一个servlet类叫做MyServlet,我这个类对应的有很多实例,wrapper就是用来管理这些实例的。
像这样,我们将我们上面第一段代码进行修改, 真实的场景应该是这样的

Class Context{
	List<Wrapper> wrappers;
}
Class Wrapper{
	List<Servlet> servlets;
}
各位观众老爷是不是明白了点什么?

tomcat之所以被称为servlet容器,可就是靠的这些容器类!!
所以各个容器的大小应该是
Engine > Host > Context > Wrapper > Servlet
每一个容器下面其实并非只有下一层容器的一个集合,其实还有一个组件,叫做pipline,会对我们的请求进行过滤,每一个pipline的最后一个过滤器都是tomcat自己内置的,用来向下一层的容器进行传递。

ps:其实tomcat在最后使用servlet实例调用我们的doGet方法的时候,其实并不是直接调用doGet方法,而是调用的service方法。
这时一些看官老爷就要问了,我的servlet没有service方法啊,确实,你是没有写,但是你继承的HttpServlet写了啊

war包和jar包的区别是什么呢?

当我们没有静态资源的时候,同时,将servlet的注册换成注解的形式(也就是web.xml文件也没有的时候), 从外表上来看,war包的内容和jar包是一样的,那么它们到底有什么区别呢?
其实,如果没有war包的话,tomcat是没有办法在webapps目录下判断你放的jar包究竟是你的应用程序还是你程序中引入的其他的jar包的,所以,就出现了war包。

在这里插入图片描述
大家可以看到,在以war包进行部署的时候,tomcat中源码是写死的,会根据.war进行寻找,所以这就是为什么需要war包

Tomcat进行部署项目的几种方式

在这里插入图片描述
大家请看上图,在tomcat中的源码已经写的很明确了,三种,以文件夹和war包的部署方式我们都清楚,那什么是以xml文件的部署形式呢?
其实哈,这里的xml文件指的就是我们tomcat中的server.xml(config文件夹下)文件
在这里插入图片描述
大家请看这个图片,其实,我们将文件夹和war包放入webapps的目录下时,其实是手动的将其可以被tomcat找到,我们也可以不将我们的文件夹和war文件放入webapps目录下,通过在server.xml中配置context这个节点, 通过配置docbase这个属性来使tomcat可以找到你的放在别处的工程, 这就是xml的方式。
这里有一个优先级的顺序,xml > war文件 > 文件夹的形式

最后,又到了说再见的时候了。
但是我们的旅途还没有结束,tomcat还有很多的知识等待我们去探索
如果本文有什么不妥的地方,欢迎留言指出,我们共同进步
发布了2 篇原创文章 · 获赞 1 · 访问量 164

猜你喜欢

转载自blog.csdn.net/weixin_44880685/article/details/104691754