你的老朋友Tomcat😺(一)

1,122 阅读5分钟

作为一个Web开发人员,我们应该很清楚我们开发的Web应用是依托于Tomcat提供服务的,Tomcat是一个Web容器,那么Tomcat的工作原理是怎样的呢?浏览器中的一个请求是怎么对应到应用程序中Controller的某个方法的呢?

一、目录结构

  • /bin:存放 Windows 或 Linux 平台上启动和关闭 Tomcat 的脚本文件。
  • /conf:存放 Tomcat 的各种全局配置文件,其中最重要的是server.xml。
  • /lib:存放 Tomcat 以及所有 Web 应用都可以访问的 JAR 文件。
  • /logs:存放 Tomcat 执行时产生的日志文件。
  • /work:存放 JSP 编译后产生的 Class 文件。
  • /webapps:Tomcat 的 Web 应用目录,默认情况下把 Web 应用放在这个目录下。

二、Tomcat的本质

Tomcat是一个Web容器,那Web容器又是什么呢?我们从Tomcat实现的功能上来看,Tomcat负责Http请求接收和响应、Tomcat负责管理Servlet。那么Tomcat本质上就是一个“HTTP服务器+Servlet容器”,在实现上Tomcat也是分为不同的组件,这样很好的消除HTTP请求处理和具体业务逻辑的耦合。它算是一个轻量级的应用服务器,Tomcat也是SpringBoot默认的嵌入式Servlet容器。

三、Servlet和SpringMVC

Servlet可以简单理解为运行在服务端的Java程序,它没有main方法,不能独立运行,必须把它部署到Servlet容器中。HTTP服务器不直接调用业务类,而是把请求交给容器来处理,容器通过Servlet接口调用业务类。Servlet接口和Servlet容器这一整套规范叫作Servlet规范。

我们使用的SpringMVC框架中实现了一个DispatcherServlet,Spring的IOC容器负责管理我们编写的Controller,DispatcherServlet负责解析请求,根据我们编写好的mapping映射关系找到对应的Controller调用相应的方法。(划重点记好笔记,很多小伙伴会误解Controller是一个Servlet)。我们来看一下Web应用程序的一个层次结构,这里我偷个懒就不画图了直接简单描述(操作系统(JVM(Tomcat(SpringMvc(Web应用)))))

四、Servlet容器

3.1 Servlet接口

Servlet.png

* service():在Servlet接口中service()方法最重要,在这个方法里实现具体业务逻辑处理,它的两个参数ServletRequest和ServletResponse是用来封装请求信息和响应信息的。我们常用的是用来处理HTTP协议的子接口HttpServletRequest和HttpServletResponse,通过HttpServletRequest可以获取所有请求相关的信息。

* init()和destroy():它们是Servlet的生命周期相关方法,分别是在容器加载Servlet类和卸载的时候调用的方法。

* getServletConfig():它的作用就是拿到封装在ServletConfig中的Servlet的初始化参数,可以在web.xml给Servlet配置参数。

接口编程中经常会有一个抽象类来实现接口和封装通用的逻辑,Servlet规范提供了GenericServlet抽象类,SpringMVC中的DispatcherServlet就是它的子类。由于大多数的Servlet都是在HTTP环境中处理的,因此Servet规范还提供了加入了HTTP特性的HttpServlet来继承GenericServlet。通过继承HttpServlet类来实现自己的Servlet,只需要重写doGet和doPost方法。

3.2 Servlet容器工作流程

外部请求某个资源时,HTTP服务器会用一个ServletRequest对象封装请求信息;Servlet容器拿到请求后,根据配置好的请求URL和Servlet的映射关系,找到相应的Servlet(如果Servlet没有被加载则创建这个Servlet,并调用init方法来完成初始化),接着调用Servlet的service方法处理请求,把ServletResponse对象返回给HTTP服务器。工作流程如图所示:

tomcat.jpg

Servlet规范里定义了ServletContext接口来对应一个Web应用。Servlet容器在启动时会加载Web应用,为每个Web应用创建唯一的ServletContext对象。一个Web应用可能有多个Servlet,这些Servlet可以通过全局的ServletContext来共享数据包括Web应用的初始化参数、Web应用目录下的文件资源等。

3.3 Filter和Listener

  • Filter过滤器,这个接口允许对请求和响应做一些统一的处理。它使用了责任链模式,原理是这样的:Web应用部署完成后,Servlet容器需要实例化Filter并把Filter链接成一个FilterChain。当请求进来时,获取第一个Filter并调用doFilter方法,doFilter方法负责调用FilterChain中的下一个Filter。

  • Listener监听器,Web应用在Servlet容器中运行时,Servlet容器内部会不断的发生各种事件,如Web应用的启动和停止、请求到达等。Servlet容器提供了一些默认的监听器来监听这些事件,当事件发生时Servlet容器会负责调用监听器的方法。用户可以定义自己的监听器去监听感兴趣的事件,将监听器配置在web.xml中。

3.4 Web应用

一般是以Web应用程序来部署Servlet的,根据Servlet规范,Web应用程序有一定的目录结构,如下所示:

|- MyWebApp
    |- ……                     -- 存放静态资源
    |- WEB-INF/web.xml        -- 配置文件,配置Servlet等
    |- WEB-INF/lib/           -- 存放Web应用所需各种JAR包
    |- WEB-INF/classes/       -- 存放应用类,比如Servlet类
    |- META-INF/              -- 目录存放工程的一些信息