关于 Tomcat 系列其他文章的传送门
-
《 如何在 10 分钟内学会 Tomcat 8 》 您当前所在位置

一、软件的架构模式¶
软件从设计上,有以下几种架构:
- 分层架构:把要实现的功能在以下四个层级中抽象的表现出来,各层级之间是隔离的,通过调用接口来完成工作;
- 表现层:主要处理业务逻辑本身;
- 业务层
- 持久层
- 数据库层:通过调用数据库,把持久层的数据保存在对应的数据库中;
- 事件驱动架构模式:可以理解是一个分布式异步架构模式,模块之间的调度高度解耦;
- 微内核架构:即插件式架构,程序核心本身设计的非常小,各种其他功能通过扩展模块的方式插入到核心中,比如 Nginx 就是这样的架构;
- 微服务架构:把整体系统功能的每一项功能,都独立为一个又一个的发布单元,每个单元都是一个独立的服务提供者,各服务之间通过服务治理系统来完成服务组件之间的交互和通信。
- API REST-based
- application REST-based
- 中心化消息
- 基于空间的架构:云原生的应用程序。
二、Tomcat 是什么¶
了解 Tomcat 之前先了解一下 Java,下图是 Java 的技术体系:
Java 技术体系¶

从下网上看,可以看出有以下几个部分:
- JVM:是 Java 虚拟机,一个专门运行 Java 的环境;
- JRE:是 JVM + 各种 JAVA2 SE API 的 标准类库 接口;
- JDK:是 JRE + Java 的开发工具,开源社区版叫
OpenJDK。
这其中,JDK 包含了 JRE,JRE 又包含了 JVM。

Java 的类库接口分为:
- 标准版:JAVA2 SE(Standard Edition) API;
- 企业版:JAVA2 EE(Enterprise Edition) API。
其中 JRE 中包含的类库就是 JAVA2 SE 标准类库,而企业版则是 JAVA2 EE 企业类库,企业版比标准版多出很多的库接口,如 Applet 和 jsp 等等。
Tomcat¶
而 Tomcat 就是在 JRE 的基础上,又包含了 Applet 和 jsp 这两个最常用的企业类库,可以看做是 J2EE 的不完整实现。
Tomcat 是 Apache 的 ASF 旗下已经毕业的开源项目,本身其实也是用 Java 程序编写的,是一个专门为了运行 jsp(java server page) 的容器,而 Tomcat 的代码名则叫 catalina。
实现了此类功能的软件其实有很多,比如:
- 商业实现:
- WebSphere
- WebLogic
- Oc4j
- Glassfish
- Geronimo
- JOnAS
- JBoss
- 开源实现:
- Tomcat
- Jetty
- Resin
JSP 代码的运行流程¶
JSP 其实也是一种 Java 代码,所以先了解一下 Java 代码的运行流程。
Java 代码的运行流程:
.java代码会被 java C 编译为.class(servlet 程序),然后 在 JVM 中运行;- JVM 则负载加载程序的类文件
*.class,及程序的类文件依赖到的其它的类文件而后运行; - 运行时整个表现为一个 JVM 进程。
JSP 代码的运行流程:
- JSP 的代码运行第一步是通过组件 jsp parser 把
*.jsp转换为*.java; - 然后就和 Java 程序运行时一样,
.java代码被 java C 编译为.class(servlet 程序),然后 在 JVM 中运行。


而编译好的 .java 和 *.class 文件会缓存在 /tomcat/work 目录下,加速下次使用,所以程序第一次部署后应该预热一下 Tomcat。
1 | # tree /usr/local/tomcat/work |
三、Tomcat 的安装和启动¶
Tomcat 本身也是个 Java 程序,所以要运行 Tomcat 就得先安装好 Java 的运行环境。
安装 JDK¶
JDK 分为社区版和企业版,下面依次介绍安装方式。
OpenJDK 社区版¶
使用 yum 可直接安装 devel 的安装包,包含了开发组件和 OpenJDK 的核心包。
1 | yum install java-1.8.0-openjdk-devel |
OpenJDK 可多版本并存,当 1.6.0, 1.7.0, 1.8.0 多版本并存时,可使用 alternatives 命令设定默认使用的版本。alternatives 就是利用软连接实现的。
/usr/bin/java 其实是个软连接,完整路径为:
1 | /usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.x86_64/jre/bin/java |
最后那个才是真正的 Java 程序目录。
Oracle JDK 企业版¶
先下载 rpm 安装包。
Oracle JDK 需要从官网下载,如商业使用需要注意版权,个人学习使用无限制。
安装。
使用 rpm 安装,默认会安装到 /usr/java 目录下。
1 | rpm -ivh jdk-8u221-linux-x64.rpm |
添加 JAVA_HOME 环境变量。
1 | vim /etc/profile.d/java.sh |
重载 shell 生效。
1 | exec bash |
能查看当前的 Java 版本,说明安装成功。
1 | java -version |
安装 Tomcat¶
接下来就可以安装 Tomcat 了。
Tomcat 也有两种安装方法,可以直接使用 yum 从 Base 仓库安装,也可以从官网下载编译好的 tar 包解压安装。
1. 通过 yum 安装¶
可以直接使用 yum 安装,Base仓库是 7.x 的版本。
1 | yum install -y tomcat tomcat-webapps tomcat-docs-webapp tomcat-admin-webapps |
- rpm 包安装的程序环境:
- 配置文件目录:
/etc/tomcat; - 主配置文件:
server.xml;
- 配置文件目录:
- 网页文件的存放位置:
/var/lib/tomcat/webapps/- examples
- manager
- host-manager
- docs
- Unit File:
tomcat.service; - 环境配置文件:
/etc/sysconfig/tomcat。
通过 systemd 就能直接启动 Tomcat 了。
1 | systemctl start tomcat |
2. 通过 tar 包安装¶
如果想用新版,需要从官网下载,当前版本是 8.5.43;
下载地址 http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.43/bin/apache-tomcat-8.5.43.tar.gz
下载的是编译好的 Java 二进制程序,接下来展开压缩包到指定位置即可完成安装。
展开 Tomcat 即可完成安装。
1 | tar -xvf apache-tomcat-8.5.43.tar.gz -C /usr/local |
Tomcat 的目录结构¶
/bin/:脚本,及启动时用到的类;/conf/:配置文件目录;/lib/:库文件,Java 类库,jar;/logs/:日志文件目录;/temp/:临时文件目录;/webapps/:网页文件的默认目录;/work/:工作目录;
配置 Tomcat 程序的权限¶
注意:建议使用普通用户运行 Tomcat,而不是 root,所以先创建普通账户并修改权限。
1 | useradd tomcat |
但是对 logs, temp, work 这些目录应该有写权限,而且对 conf/* 应该有读的权限,否则会因为加载不了配置信息而无法启动。
1 | chown -R tomcat: /usr/local/tomcat/{logs/,temp/,work/} |
运行 Tomcat¶
先切换到 tomcat 用户,然后使用 startup.sh 脚本来启动 Tomcat。
1 | [root@node1 ~]# su - tomcat |
或者配置环境变量。
1 | [root@node1 ~]# vim /etc/profile.d/tomcat.sh |
环境变量生效后,就可以通过命令 startup.sh 直接启动 Tomcat 了。
1 | [root@node1 ~]# startup.sh |
catalina.sh 工具¶
使用 /usr/local/tomcat/bin/catalina.sh 工具可以完成很多控制动作:
1 | catalina.sh --help |
四、Tomcat 的程序结构¶
配置文件介绍¶
Tomcat 的配置文件放置在 tomcat/conf/ 下,yum 安装的话会在 /etc/tomcat/conf/下。
server.xml:主配置文件;web.xml:提供默认的与部署相关的配置;每个 webapp 都可以有自己的web.xml,存放位置为WEB-INF/目录中,如果没有,则此文件会提供默认部署配置;context.xml:提供默认的配置文件;每个 webapp 都可以有专用的配置文件,它通常由专用的配置文件context.xml来定义,其存放位置为WEB-INF/目录中;如果没有,此文件会提供默认配置;tomcat-users.xml:关于 basic 用户认证的账号和密码文件;catalina.policy:当使用-security选项启动 Tomcat 时,用于为 Tomcat 设置安全策略;catalina.properties:主要配置 Tomcat 的安全设置、类加载设置、不需要扫描的类设置、字符缓存设置,以及一些与 JVM 调优相关参数;/tomcat.conf:一些变量的配置;logging.properties:日志系统相关的配置。
JSP WebAPP 的组织结构¶
tomcat/weball/:webapps 的根目录,放置各种与站点相关的目录;index.jsp,index.html:主页文件;WEB-INF/:当前 webapp 的私有资源路径;通常用于存储当前 webapp 的web.xml和context.xml配置文件;META-INF/:类似于 WEB-INF/;classes/:类文件,当前 webapp 所提供的类;lib/:类文件,当前 webapp 所提供的被打包为 jar 格式的类;ROOT:存放网站首页的目录。
webapp 归档格式¶
webapp 在发布时通常是被打包为一个归档文件,有如下几种格式:
*.war:webapp;*.jar:EJB 的类打包文件;*.rar:资源适配器类打包文件;*.ear:企业级 webapp。
五、JSP 部署 webapp 的相关操作¶
部署操作有以下几种¶
- 部署(deploy)流程:
- 将 webapp 的源文件放置于目标目录(网页程序文件存放目录),配置 Tomcat 服务器能够基于
web.xml和context.xml文件中定义的路径来访问此 webapp; - 将其特有的类和依赖的类通过 class loader 装载至 JVM 虚拟机;
- 将 webapp 的源文件放置于目标目录(网页程序文件存放目录),配置 Tomcat 服务器能够基于
- 部署有两种方式:
- 自动部署:由 Tomcat 自动完成;
- 手动部署:
(1) 冷部署:把 webapp 复制到指定的位置,而后启动 Tomcat;
(2) 热部署:在不停止 Tomcat 的前提下进行部署;部署工具包括:manager、ant 脚本、tcd(tomcat client deployer)等;
- 反部署(undeploy):
- 停止 webapp,并从 Tomcat 实例上卸载 webapp;
- start:启动处于停止状态的 webapp;
- stop:停止 webapp,不再向用户提供服务;其类依然在 jvm 上;
- redeploy:重新部署;
冷部署示例¶
手动创建一个测试类应用,并冷部署。
1、创建名为 myapp 的工作目录。
1 | mkdir -pv /usr/local/tomcat/webapps/myapp/{classes,lib,WEB-INF} |
2、创建 jsp 主页文件。
vim /usr/local/tomcat/webapps/myapp/index.jsp
1 | <%@ page language="java" %> |
3、就可以访问了
1 | curl http://192.168.50.12:8080/myapp/ |
4、在 tomcat/work/.../myapp/ 目录下可以看到自动转换并生成的 *.java 和 *.class 文件。
1 | # tree /usr/local/tomcat/work |
六、部署 Tomcat 的两个管理应用¶
- Manager:管理 webapps 应用程序;
- Host Manager:管理虚拟主机。
登录管理界面需要先创建账户,并为每个账户分配不同的角色,每个角色的权限也各不相同
- Manager App 的角色:
- manager-gui:允许访问 HTML GUI 和状态页;
- manager-script:允许访问文本界面和状态页;
- manager-jmx:允许访问 JMX 代理和状态页;
- manager-status:只允许访问状态页;
- Host Manager 的角色:
- admin-gui:Host Manager 的管理角色。
配置示例¶
编辑 tomcat-users.xml 添加账户并分配角色:
1 | vim /usr/local/tomcat/conf/tomcat-users.xml |
在 <tomcat-users> 上下文中,添加对账户的权限配置。
1 | <tomcat-users |
重启 Tomcat 后,就可以访问管理界面,对 Tomcat 进行启动、停止、反部署等管理操作。
管理页面的入口在首页的这里:

查看是否对 IP 做了限制:
如果访问时提示 403 Access Denied 被拒绝,可能因为 tomcat 默认对 IP 做了限制。
解决办法:
在 tomcat/webapps/manager 和 tomcat/webapps/host-manager/ 下都有一个 /META-INF/context.xml 文件,注释两个文件中掉其中对 IP 的限制信息即可。
1 | <!-- |
七、server.xml 中常用组件的配置¶
server.xml 是 Tomcat 的核心配置文件,内部通过组件来定义,每一个组件都由一个 Java 的“类”实现,这些组件大体可分为以下几个类型:
- 顶级组件:
Server; - 服务类组件:
Service; - 连接器组件:
http,https,ajp(apache jserv protocol); - 容器类:
Engine,Host,Context; - 被嵌套类:
valve,logger,realm,loader,manager, …; - 集群类组件:
listener,cluster, …;
组件的框架¶
1 | <Server> // 定义一个实例,内部有一个或多个 Service |
注意:server.xml 不应该让其他用户有权限访问。
下面了解各组件的功能和使用方法。
Server 组件¶
默认配置:<Server port="8005" shutdown="SHUTDOWN">。
Server 代表了 tomcat instance,表现为一个 Java 进程,监听在 本机地址 的 8005 端口,属于管理端口,只接收 SHUTDOWN 关键字;
- 各 Server 监听的端口不能相同,因此,在同一物理主机启动多个实例时,需要修改其监听端口为不同的端口;
注意:
- 因为可使用
SHUTDOWN关键字直接关闭 Tomcat 的 Java 进程。 - 这个操作非常危险,应关闭此端口或更换为复杂的关键字。
1 | # telnet 127.0.0.1 8005 |
1 | # openssl rand -base64 10 # 生成随机数 |
替换关键词
1 | <Server port="8005" shutdown="5VG/92mOgrKdLw"> |
Service 组件¶
用于实现将一个或多个 connector 组件关联至一个 engine 组件。
Connector 组件¶
定义属于整个 Tomcat 的监听地址和端口,负责接收请求。
- 常见的连接器有三类:
- http
- https
- ajp
进入 Tomcat 的请求可分为两类:
-
standalone: 直接接收来自于客户端浏览器的请求;
-
由其它的 web server 反代,请求是来自前端的反代服务器;
nginx->http connector->tomcat;httpd(proxy_http_module)->http connector->tomcat;httpd(proxy_ajp_module)->ajp connector->tomcat;httpd(mod_jk)->ajpconnector->tomcat。
连接器可以使用的一些属性:
port="8080":定义端口。注意:Tomcat 最好使用普通用户启动,所以无法使用1024以下的端口;protocol="HTTP/1.1":定义默认使用的协议版本;connectionTimeout="20000":连接超时时长,单位毫秒;address:监听的 IP 地址,默认为本机所有可用地址;maxThreads:最大并发连接数,默认为200;enableLookups:是否启用DNS查询功能;URIEncoding="UTF-8":如果 uri 内有中文,一定要指定编码格式为 UTF8;acceptCount:等待队列的最大长度;secure:启用 SSL;sslProtocol:定义 SSL 证书、版本、私有文件。
示例:定义一个连接器¶
1 | <Connector port="10080" protocol="HTTP/1.1" |
Engine 组件¶
每个 Engine 代表一个 Servlet 实例,即 servlet 引擎,是可以运行代码的位置,其内部可以一个或多个 host 组件来定义虚拟主机,有多个虚拟主机时通常需要通过 defaultHost 属性来定义默认的虚拟主机;
常用属性:
name="Catalina":基本上均为Catalina;defaultHost="localhost":定义默认的虚拟主机,使用 Host 中定义的名字;jvmRoute=TAG:基于 cookie 的会话绑定时,赋予当前 Engine 一个唯一的标识符。
Host 组件¶
Host 其实就是定义基于主机名的虚拟主机,位于 Engine 内部用于接收请求并进行相应处理。
注意:Tomcat 仅支持基于主机名的虚拟主机。
Host 基础配置¶
1 | <Host name="localhost" appBase="webapps" |
常用属性说明¶
name:定义虚拟主机名;appBase:定义网页文件根目录,指存放非归档的 web 应用程序或归档的 WAR 文件目录路径;- 注意:使用相对路径时是基于
$CATALINA_BASE变量所定义的路径;
- 注意:使用相对路径时是基于
unpackWARs:如果appBase内有一个 WAR 文件,是否自动展开;autoDeploy:在 Tomcat 处于运行状态时,有新的某 webapp 放置于 appBase 所定义的目录中时,是否自动将其部署至 Tomcat。- 生产环境不建议开启。
示例:定义一个新的 Host¶
1、添加一个 Host
1 | <Host name="node1.monster.com" appBase="/data/myapp" unpackWARs="true" autoDeploy="true"> |
2、在 ROOT 中提供一个网站首页测试页
1 | mkdir -pv /data/myapp/ROOT/{lib,classes,WEB-INF} |
1 | <%@ page language="java" %> |
3、重启 tomcat 后访问 http://node1.monster.com:8080,可以看到新页面就说明成功了。
1 | curl node2.monster.com:8080 |
Context 组件¶
可以自定义 url 和网页文件目录的对应关系,类似于 Apache 中的 alias 别名。
Context 基础配置¶
1 | <Context path="/uri" docBase="/PATH/TO/SOMEDIR" reloadable=""/> |
Context path="/PATH":定义 uri 路径;docBase="/PATH/TO/SOMEDIR":网页文件路径;reloadable="":是否支持自动重载。
Context 示例¶
访问 node1.monster.com/jump/* 时,本来应该是访问 /data/myapp/jump/ 下的文件,
配置 Context 后,实际是访问,/data/jumphome/ 下的文件。
1 | <Host name="node1.monster.com" appBase="/data/myapp" unpackWARs="true" autoDeploy="true"> |
Valve 组件¶
使用 Valve 在 Host 中定义一种功能阀门。
定义访问日志的 Valve¶
使用 org.apache.catalina.valves.AccessLogValve
1 | <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" |
directory="logs":日志存放目录,相对路径为$CATALINA_BASE的目录下;prefix="localhost_access_log":日志文件的前缀,中间是日期;suffix=".txt":日志文件的后缀;pattern="%h %l %u %t "%r" %s %b":定义日志格式。
Tomcat 官方关于日志中变量的对应关系
https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/catalina/valves/AbstractAccessLogValve.html
定义访问控制的 Valve¶
使用 org.apache.catalina.valves.RemoteAddrValve
1 | <Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="192\.168\.50\.20"/> |
Value 综合示例¶
1 | <Host name="node1.monster.com" appBase="/data/myapp" unpackWARs="true" autoDeploy="true"> |
