Tomcat 的使用及原理分析(IDEA版)

时间:2022-07-22
本文章向大家介绍Tomcat 的使用及原理分析(IDEA版),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

文章目录
  • 一、预备知识
    • 1、软件架构
    • 2、资源分类
    • 3、网络通信三要素
    • 4、服务器软件:
    • 5、web 服务器软件

  • 二、Tomcat 的使用
    • 1、下载
    • 2、安装
    • 3、卸载
    • 4、启动
    • 5、Tomcat 启动可能遇到的问题
    • 6、关闭
    • 7、配置
  • 三、Tomcat 集成 intelliJ IDEA
    • 1、首先新建一个项目,选择 `java EE`
    • 2、创建完成
    • 3、配置 Tomcat
    • 4、启动项目
    • 5、虚拟目录
    • 6、端口
    • 7、从一般到特殊
    • 8、IDEA 的热部署
  • 四、IDEA 集成 Tomcat 分析
  • 五、Tomcat 原理分析
    • 1、Tomcat 的组成
    • 2、Tomcat 的启动流程
    • 3、Web 应用的部署方式
    • 4、Servlet
    • 5、JSP 引擎
  • 六、总结

一、预备知识

这部分内容时理解 Tomcat 的基础,主要介绍服务器的概念。

1、软件架构

1. C/S:客户端/服务器端
2. B/S:浏览器/服务器端

2、资源分类

1. 静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源.静态资源可以直接被浏览器解析
	* 如: html,css,JavaScript
2. 动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资源,在返回给浏览器
	* 如:servlet/jsp,php,asp....

3、网络通信三要素

1. IP:电子设备(计算机)在网络中的唯一标识。
2. 端口:应用程序在计算机中的唯一标识。 0~65536
3. 传输协议:规定了数据传输的规则
	1. 基础协议:
		1. tcp:安全协议,三次握手。 速度稍慢
		2. udp:不安全协议。 速度快

4、服务器软件:

  • 服务器就是安装了服务器软件的计算机,它的硬盘比较大,内存比较多,CPU性能好。
  • 比如电脑安装了 MySQL 服务器软件,那么这台电脑就可以作为服务器,因为它可以让别的电脑访问到然后操作 MySQL 里的数据。
  • 那么安装了 Web 服务器软件,那么这台电脑就可以作为 Web 服务器,让别的电脑访问到。

服务器软件的作用就是可以接收用户的请求,处理请求,做出响应。

5、web 服务器软件

web服务器软件中,可以部署 web 项目,让用户通过浏览器来访问这些项目。

之前我们的角色是用户,将来我们的角色内容提供者,让别人通过浏览器来访问我们写的项目。

动态资源不能够自动运行,他们只能运行在 Web 服务器软件中。

所以也被称为 Web容器,也就是说动态资源必须在容器中才能运行。

而我们要学习的 Tomcat 就是这样一款 Web 服务器软件。

二、Tomcat 的使用

1、下载

http://tomcat.apache.org/

2、安装

解压压缩包即可。
  • 注意:安装目录建议不要有中文和空格

解压完之后如图所示:

每个文件夹内容:

3、卸载

删除目录就行了

4、启动

1、`bin/startup.bat` ,双击运行该文件即可
2、访问:
	浏览器输入:
	http://localhost:8080 	访问自己
	http://别人的ip:8080 	访问别人

5、Tomcat 启动可能遇到的问题

  1. 黑窗口一闪而过
  • 原因: 没有正确配置JAVA_HOME环境变量
  • 解决方案:正确配置JAVA_HOME环境变量
  1. 启动报错

暴力法:找到占用的端口号,并且找到对应的进程,杀死该进程

netstat -ano

温柔法:修改自身的端口号

在下面的文件中修改

conf/server.xml
<Connector port="8888" protocol="HTTP/1.1"
		               connectionTimeout="20000"
		               redirectPort="8445" />

一般会将tomcat的默认端口号修改为80。 80端口号是http协议的默认端口号。 好处:在访问时,就不用输入端口号

6、关闭

1、正常关闭:
	bin/shutdown.bat
	ctrl+c
2、强制关闭:
	点击启动窗口的×

7、配置

这里才是最重要的

部署项目的方式:

  1. 直接将项目放到 webapps 目录下:

将项目打成一个war包,再将war包放置到webapps目录下。war包会自动解压缩

  1. 配置 conf/server.xml 文件: 在标签体中配置
<Context docBase="D:hello" path="/hehe" />
//docBase是项目存放目录
//hehe是虚拟目录
  1. confCatalinalocalhost创建任意名称的xml文件 在文件中编写:
<Context docBase="D:hello" />
//虚拟目录:xml文件的名称
java动态项目的目录结构:
					-- 项目的根目录
						-- WEB-INF目录:
							-- web.xml:web项目的核心配置文件
							-- classes目录:放置字节码文件的目录
							-- lib目录:放置依赖的jar包

三、Tomcat 集成 intelliJ IDEA

1、首先新建一个项目,选择 java EE

选择 Tomcat Server

选择本地的包,选最外层的文件夹就可以了,选好了之后下面的 Tomcat base directory 他会自动生成:

Application Server 选择你本地解压的 Tomcat 的包的位置。

注意这里要勾上

当然不勾也可以,我们也可以手动创建这些包,但是自动生成会方便一些。

2、创建完成

创建完成之后的目录结构应该是这样的:

你可以看到,该有的包都已经自动导入了。

3、配置 Tomcat

选择 run 下面的 Edit Configurations

点击Template拓展窗口

找到 Tomcat,选择local

然后配置到你本地的 Tomcat 地址,端口什么的保持原样就可以了

然后点击 Apply OK 关掉就可以了。

4、启动项目

配置好了之后选择你的Tomcat,然后启动:

我这里稍微改造了一下 index.html 界面,如图所示:

贴出来代码:

<%--
  Created by IntelliJ IDEA.
  User: wsuo
  Date: 2020/2/26
  Time: 16:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>18103330219-王硕</title>
    <style>
        #d1 {
            width: 600px;
            height: 400px;
            background-color: antiquewhite;
            text-align: center;
            border-radius: 10%;
            margin-top: 140px;
            margin-left: 450px;
            position: absolute;
        }

        .font {
            color: darkorange;
            font-weight: bolder;
            text-align: center;
        }
    </style>
</head>
<body>
<div id="d1">
    <h1 class="font">计算机182 ** 1810333**** 男</h1>
    <%
        String a = "abc";
        System.out.println(a);
        out.println(a + "d");
    %>
</div>
</body>
</html>

运行在浏览器端是这样子的:

这样你的IDEA集成 Tomcat 就成功了!


5、虚拟目录

这里稍微多讲一点,关于虚拟目录

如果你细心的话会发现我的项目网址名称很难看:

其中的这个wsProject_war_exploded就是你的虚拟目录

什么意思呢,就是你要在路径名称上加上这句才可以访问到,哪有的同学说你这个太难看了,我可以换个吗,当然可以,你可以随时打开如下图的配置:

点击之后选择 Deployment 然后看下图:

其中这个 Application Context 就是你的虚拟目录,你想改成什么都可以,这样你的访问路径就会发生相应的变化:

比如我如果设置成这样:

那么我访问的时候浏览器的地址就应该是:

http://localhost:8080/index.jsp

如果设置成abcd 那么我访问的时候浏览器的地址就应该是:

http://localhost:8080/abcd/index.jsp

6、端口

再来聊一下端口

细心的你会发现,我们的地址栏冒号后面有个8080,那为什么是8080呢,我填8089行不行?

答案是不行的,但是我们可以配置:

将这个数字改成你想要的的都可以,但是注意可能会有端口占用的问题,这样的话你可以选择我们之前提到的暴力法或者温柔法解决它。

注意一点就是如果你设置成 80端口,那么你就不用填写端口了: 比如上面的地址可以进一步简化为:

http://localhost/index.jsp

因为 80 端口是浏览器的默认端口!

就好像你在 计182 班级里面不用加 计182 的前缀一样,因为大家都知道你是182班的。

7、从一般到特殊

OK,我们回过来看这个页面:

路径:

http://localhost:8080/wsProject_war_exploded/index.jsp

我们已经知道端口虚拟目录了,那么后面的index.jsp是什么鬼呢???

可以换吗?

当然可以,看图:

从图中可以看出,index是直属于web文件夹的,而 web 是一个 webapp 的核心,所以index就是直接在项目根目录下的。

如果我们把index放进一个文件夹里比如file里,那么访问路径就要改为:

http://localhost:8080/wsProject_war_exploded/file/index.jsp

那如果我们不想访问index.jsp呢,比如想访问 hello.html:

贴出来代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
<h1>
    你好我是Hello.html!
</h1>
</body>
</html>

我们新建了web/file/hello.html,于是可以在浏览器输入地址访问:

http://localhost:8080/wsProject_war_exploded/file/hello.html

还有就是 index.jsp,本身比较特殊,就算我们不写也可以访问到,这是因为名字特殊,是一个默认值,这在后面学习 web.xml 中会讲到.

8、IDEA 的热部署

如果你跟着我一起做了,相信你一定深有体会,改变文件内容之后一定要重新启动服务器,不然改动效果不会生效。这在开发过程中是很烦的,为了解决这个问题,我们可以使用以下办法(如果你的IDEA使用本来就很卡顿不建议这么做):

修改为上面在每次新建文件的时候就可以不用每次都重启服务器了。

如果你改为:

这样你以后再写 java 代码的时候也可以不用重启服务器了,但是并不推荐这样做,因为java代码的修改次数比较频繁。

由于篇幅原因,有关 Tomecat 的原理部分请看我的另外一篇文章。

四、IDEA 集成 Tomcat 分析

IDEA会为每一个 Tomcat 部署的项目单独建立一份配置文件。

那么这个配置文件在哪呢?

我们先启动一个项目:

观察控制台的输出:

观察到有 Using CATALINA_BASE,这个的意思就是使用的工作目录,也就是 工作空间项目。

C:Users13343.IntelliJIdea2019.2systemtomcatTomcat_8_5_31_wsProject

然后我们顺着这个路径去电脑上面查看:

在 conf 里面有一大推配置文件:

这里有很多的配置文件,我们可以打开进行修改端口什么的,但是现在都是 IDEA 磅我们生成好了,通过图形化界面自动生成好了,所以IDEA简化了我们的开发,这就好像计算机指令与图形化界面的关系一样。

然后我们继续往下看:

打开 confCatalinalocalhost

发现有一个文件,还是以我们的项目名称命名的!

打开看看:

发现有一个路径,这是Tomcat部署的web项目:

D:developIDEA_2017IdeaProjectslsu_studywsProjectoutartifactswsProject_war_exploded

在电脑中打开:

这就是我们之前所说的第三种项目的部署方式,这里IDEA又帮我们自动生成了。

就是这个:

confCatalinalocalhost创建任意名称的xml文件

  • 他就相当于在 webapps 目录下放了一个 war 包。
  • 你工作空间的out目录下面就是Tomcat的项目部署的地方。
  • 这个才是 Tomcat 真正访问的项目。

而 Tomcat部署的web项目 目录下会有一个 classes ,这里的文件从哪里来呢?

从你的项目的 src 目录下来的。例子中的项目 src 目录为空,所以没有 classes 文件夹。

仔细看上面两个目录,你会发现,web目录其实就是 Tomcat部署的web项目 的根目录!

五、Tomcat 原理分析

1、Tomcat 的组成

如下图:

Server: Tomcat 封装的、对外提供完整的、基于组件的 web 服务,包含 Connectors、Container 两个核心组件,以及多个功能组件,各个 Service 之间是独立的,但是共享 同一 JVM 的资源;

Connector: Tomcat 与外部世界的连接器,监听固定端口接收外部请求,传递给 Container,并将 Container 处理的结果返回给外部;

Container: Catalina,Servlet 容器,内部有多层容器组成,用于管理 Servlet 生命周期,调用 servlet 相关方法。

Loader: 封装了 Java ClassLoader,用于 Container 加载类文件;

Realm: Tomcat 中为 web 应用程序提供访问认证和角色管理的机制;

JMX: Java SE 中定义技术规范,是一个为应用程序、设备、系统等植入管理功能的框架,通过 JMX 可以远程监控 Tomcat 的运行状态;

Jasper: Tomcat 的 Jsp 解析引擎,用于将 Jsp 转换成 Java 文件,并编译成 class 文件。

Session: 负责管理和创建 session,以及 Session 的持久化(可自定义),支持 session 的集群。

Pipeline: 在容器中充当管道的作用,管道中可以设置各种 valve(阀门),请求和响应在经由管 道中各个阀门处理,提供了一种灵活可配置的处理请求和响应的机制。

Naming: 命名服务,JNDI, Java 命名和目录接口,是一组在 Java 应用中访问命名和目录服务的 API。命名服务将名称和对象联系起来,使得我们可以用名称访问对象,目录服务也是一种命名服务,对象不但有名称,还有属性。Tomcat 中可以使用 JNDI 定义数据源、配置信息,用于开发与部署的分离。


Container的组成:

Engine: Servlet 的顶层容器,包含一 个或多个 Host 子容器;

Host: 虚拟主机,负责 web 应用的部 署和 Context 的创建;

Context: Web 应用上下文,包含多个 Wrapper,负责 web 配置的解析、管理所有的 Web 资源;

Wrapper: 最底层的容器,是对 Servlet 的封装,负责 Servlet 实例的创建、执行和销毁。


2、Tomcat 的启动流程

1、启动从 Tomcat 提供的 start.sh 脚本开始

我们点击这个:

shell 脚本会调用 Bootstrap 的 main 方法,实际调用了 Catalina 相应的 load、start 方法。

2、解析配置文件

然后 load 等方法会读取 conf 文件夹下的配置文件:

在解析的过程中会根据 xml 中的关系 和配置信息来创建容器,并设置相关的属性。接着 Catalina 会调用 StandardServer 的 init 和 start 方法进行容器的初始化和启动。

3、生命周期

按照 xml 的配置关系,server 的子元素是 service,service 的子元素是顶层容器 Engine,每层容器有持有自己的子容器,而这些元素都实现了生命周期管理的各个方法,因此就很容易的完成整个容器的启动、关闭等生命周期的管理。

4、监听端口

StandardServer 完成 init 和 start 方法调用后,会一直监听来自 8005 端口(可配置),如果接收到 shutdown 命令,则会退出循环监听,执行后续的 stop 和 destroy 方法,完成 Tomcat 容器的 关闭。同时也会调用 JVM 的 Runtime.getRuntime() .addShutdownHook 方法,在虚拟机意外退出的时候来关闭容器。

5、ContainerBase

所有容器都是继承自 ContainerBase,基类中封装了容器中的重复工作,负责启动容器相关的组 件 LoaderLoggerManagerClusterPipeline,启动子容器(线程池并发启动子容器,通过 线程池 submit 多个线程,调用后返回 Future 对象,线程内部启动子容器,接着调用 Future 对象 的 get 方法来等待执行结果)。

3、Web 应用的部署方式

catalina.home 是 安装目录
catalina.base 是 工作目录 即 webapps

Server.xml:

  • 配置 Host 元素;
  • 指定 appBase 属性;
  • 配置 Context 元素;
  • 指定 docBase 元素;
  • 指定 web 应用的路径

HostConfig 监听了 StandardHost 容器的事件,在 start 方法中解析上述配置文件:

  • 扫描并解析 webapps 下的所有文件夹和 war 包,解析各个应用的 META-INF / context.xml,并创建 StandardContext,并将 Context 加入到 Host 的子容器中。

ContextConfig 解析 context.xml 顺序:

  • 先解析全局的配置 config/context.xml
  • 然后解析 Host 的默认配置 EngineName/HostName/context.xml.default
  • 最后解析应用的 META-INF/context.xml

ContextConfig 解析 web.xml 顺序:

  • 先解析全局的配置 config/web.xml
  • 然后解析 Host 的默认配置 EngineName/HostName/web.xml.default 接着解析应用的 WEB-INF/web.xml
  • 扫描应用 WEB-INF/lib/下的 jar 文件,解析其中的 META-INF/web-fragment.xml 最后合并 xml 封装成 WebXml,并设置 Context

4、Servlet

Servlet 是用 Java 编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。

它由 wrapper 封装;生命周期如下:

  1. 请求到达 server 端,server 根据 url 映射到相应的 Servlet
  2. 判断 Servlet 实例是否存在,不存在则加载和实例化 Servlet 并调用 init 方法
  3. Server 分别创建 Request 和 Response 对象,调用 Servlet 实例的 service 方法(service 方法内部会根据 http 请求方法类型调用相应的 doXXX 方法)
  4. doXXX 方法内为业务逻辑实现,从 Request 对象获取请求参数,处理完毕之后将结果通过 response 对象返回给调用方
  5. 当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方 法。

请求处理过程:

  1. 根据 server.xml 配置的指定的 connector 以及端口监听 http、或者 ajp 请求
  2. 请求到来时建立连接,解析请求参数,创建 Request 和 Response 对象,调用顶层容器 pipeline 的 invoke 方法
  3. 容器之间层层调用,最终调用业务 servlet 的 service 方法
  4. Connector 将 response 流中的数据写到 socket 中

Pipeline 与 Valve :

Pipeline 可以理解为现实中的管道,Valve 为管道中的阀门,Request 和 Response 对象在管道中 经过各个阀门的处理和控制。

  • 每个容器的管道中都有一个必不可少的 basic valve,其他的都是可选的,basic valve 在管道中最 后调用,同时负责调用子容器的第一个 valve。
  • 各层容器对应的 basic valve 分别是 StandardEngineValveStandardHostValveStandardContextValveStandardWrapperValve

5、JSP 引擎

JSP 生命周期:

  • 编译阶段:servlet 容器编译 servlet 源文件,生成 servlet 类
  • 初始化阶段:加载与 JSP 对应的 servlet 类, 创建其实例,并调用它的初始化方法
  • 执行阶段:调用与 JSP 对应的 servlet 实例的 服务方法
  • 销毁阶段:调用与 JSP 对应的 servlet 实例的 销毁方法,然后销毁 servlet 实例

如图,JSP文件会被解析为 servlet 类。

这是随便拿的一个栗子,将上面的文件打开,可以看到有一部分文件正是将HTML标签写入到页面上。

六、总结

看完了之后是不是感觉 Tomcat 不是那么神奇了?甚至感觉自己可以手写一个 Tomcat?

对,其实他就是一个服务器软件,我们在浏览器输入一个地址,完了之后能访问到页面,这里面 Tomcat 为我们做了很多工作,比如这个地址:

http://localhost:8080/abcd/index.jsp

模拟一下浏览器访问哈:

  • 首先由 localhost 找到了对应的主机,也就是服务器;
  • 然后由 8080 找到了对应的应用程序,也就是 Tomcat ;
  • 通过abcd可以找到当前 Tomcat 下面部署的项目;
  • 最后那个index.jsp就是资源名称。