200字
Tomcat的JAVA应用部署和常见配置详解
2026-03-16
2026-03-16

Java 应用部署

tomcat的根目录结构

Tomcat中默认网站根目录是**$CATALINA_BASE**/webapps/

在Tomcat中部署主站应用程序和其他应用程序,和之前WEB服务程序不同。

nginx

假设在nginx中部署2个网站应用eshop、forum,假设网站根目录是/data/nginx/html,那么部署可以是这样的。

eshop解压缩所有文件放到 /data/nginx/html/ 目录下,forum 的文件放在 /data/nginx/html/forum/ 下。

最终网站链接有以下对应关系

http://localhost/ 对应于eshop的应用,即 /data/nginx/html/
http://localhost/forum/ 对应于forum的应用,即/data/nginx/html/forum/

Tomcat

Tomcat中默认网站根目录是**$CATALINA_BASE**/webapps/

在Tomcat的webapps目录中,有个非常特殊的目录ROOT,它就是网站默认根目录。

将eshop解压后的文件放到这个**$CATALINA_BASE**/webapps/ROOT中。

bbs解压后文件都放在**$CATALINA_BASE**/webapps/forum目录下。

$CATALINA_BASE/webapps下面的每个目录都对应一个Web应用,即WebApp

最终网站链接有以下对应关系

http://localhost/ 对应于eshop的应用WebApp,即$CATALINA_BASE/webapps/ROOT/目录,
http://localhost/forum/ 对应于forum的应用WebApp,即$CATALINA_BASE/webapps/forum/

如果同时存在**CATALINA_BASE** /webapps/ROOT/forum ,仍以 CATALINA_BASE/webapps/forum/ 优先生效

每一个虚拟主机都可以使用appBase指令配置自己的站点目录,使用appBase目录下的ROOT目录作为主站目录。

范例: 主页目录和编码

[root@centos8 ~]#cat /usr/local/tomcat/webapps/ROOT/index.html
<h1>Ayaka</h1>

[root@centos8 ~]#curl 10.0.0.8:8080/index.html -I
HTTP/1.1 200
Accept-Ranges: bytes
ETag: W/"22-1594212097000"
Last-Modified: Wed, 08 Jul 2020 12:41:37 GMT
Content-Type: text/html #tomcat无指定编码,浏览器自动识别为GBK,可能会导致乱码
Content-Length: 22
Date: Wed, 08 Jul 2020 13:06:03 GMT

#httpd服务器默认指定编码为UTF-8,因为服务器本身不会出现乱码
#nginx服务器默认在响应头部没有批定编码,也会出现乱码

[root@centos8 ~]#curl 10.0.0.18/index.html -I
HTTP/1.1 200 OK
Date: Wed, 08 Jul 2020 13:07:57 GMT
Server: Apache/2.4.37 (centos)
Last-Modified: Wed, 08 Jul 2020 12:59:55 GMT
ETag: "16-5a9edaf39d274"
Accept-Ranges: bytes
Content-Length: 22
Content-Type: text/html; charset=UTF-8

#浏览器的设置默认不是UTF-8,可能会导致乱码
#修改网页指定编码
[root@centos8 ~]#cat /usr/local/tomcat/webapps/ROOT/index.html
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>tomcat</title>
</head>
<h1>我是朱诺</h1>

JSP WebApp目录结构

$CATALINA_BASE/webapps下面的每个目录对应的WebApp,可能有以下子目录,但下面子目录是非必须的

  • 主页配置:默认按以下顺序查找主页文件 index.html,index.htm、index.jsp
  • WEB-INF/:当前目录WebApp的私有资源路径,通常存储当前应用使用的web.xml和context.xml配置文件
  • META-INF/:类似于WEB-INF,也是私有资源的配置信息,和WEB-INF/目录一样浏览器无法访问
  • classes/:类文件,当前webapp需要的类
  • lib/:当前应用依赖的jar包

主页设置

全局配置实现修改默认主页文件

默认情况下 tomcat 会在**$CATALINA_BASE**/webapps/ROOT/目录下按以下次序查找文件,找到第一个则进行显示

  • index.html
  • index.htm
  • index.jsp

可以通过修改 $CATALINA_BASE/conf/web.xml 中的下面 <welcome-file-list>标签 内容修改默认页文件

范例: 修改默认主页文件

[root@centos8 tomcat]#pwd
/usr/local/tomcat
[root@centos8 tomcat]#echo '<h1>www.aya.org</h1>' > webapps/ROOT/index.html
[root@centos8 tomcat]#curl http://127.0.0.1:8080/
<h1>www.aya.org</h1>

[root@centos8 tomcat]#tail conf/web.xml
    <!-- here, so be sure to include any of the default values that you wish -->
    <!-- to use within your application. 										-->
    
		<welcome-file-list>
			<welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
		</welcome-file-list>

</web-app>
[root@centos8 tomcat]#systemctl restart tomcat
[root@centos8 tomcat]#curl http://127.0.0.1:8080/

WebApp的专用配置文件

将上面主配置文件conf/web.xml中的 <welcome-file-list>标签 内容,复制到/usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml中,如下所示:

范例: 针对主站点根目录设置专用配置文件

[root@centos8 tomcat]#vim webapps/ROOT/WEB-INF/web.xml
[root@centos8 tomcat]#cat webapps/ROOT/WEB-INF/web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
						http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1"
	metadata-complete="true">
    
    <display-name>Welcome to Tomcat</display-name>
    <description>
        Welcome to Tomcat
	</description>
		<welcome-file-list>
			<welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
		</welcome-file-list>
</web-app>

#配置修改后,无需重启tomcat服务,即可观察首页变化
[root@centos8 tomcat]#curl http://127.0.0.1:8080/

范例: 针对特定APP目录设置专用配置文件

[root@centos8 tomcat]#cp -a webapps/ROOT/WEB-INF/ webapps/nya/
[root@centos8 tomcat]#echo /usr/local/tomcat/webapps/nya/test.html > webapps/nya/test.html

[root@centos8 tomcat]#tree webapps/nya/
webapps/nya/
├── index.htm
├── index.html
├── test.html
└── WEB-INF
	└── web.xml
	
[root@centos8 tomcat]#cat webapps/nya/WEB-INF/web.xml
<description>
        Welcome to Tomcat
	</description>
		<welcome-file-list>
			<welcome-file>test.html</welcome-file>#修改默认页面文件的顺序
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
		</welcome-file-list>
</web-app>

#注意修改属性
[root@centos8 tomcat]#chown -R tomcat.tomcat webapps/nya/

[root@centos7 ~]#curl http://www.aya.org:8080/nya/
/usr/local/tomcat/webapps/nya/test.html

配置规则:

  • webApp的专有配置优先于系统的全局配置
  • 修改系统的全局配置文件,需要重新启动服务生效
  • 修改 webApp的专有配置,无需重启即可生效

应用部署实现

WebApp应用的归档格式

  • .war:WebApp打包,类zip格式文件,通常包括一个应用的所有资源,比如jsp,html,配置文件等
  • .jar:EJB类文件的打包压缩类zip格式文件,,包括很多的class文件, 网景公司发明
  • .rar:资源适配器类打包文件,目前已不常用
  • .ear:企业级WebApp打包,目前已不常用

传统应用开发测试后,通常打包为war格式,这种文件部署到Tomcat的webapps目录下,并默认会自动解包展开和部署上线。

#conf/server.xml中文件配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

部署方式

  • 部署Deploy:将webapp的源文件放置到目标目录,通过web.xml和context.xml文件中配置的路径就可以访问该webapp,通过类加载器加载其特有的类和依赖的类到JVM上,即:最终用户可以通过浏览器访问该应用
    • 自动部署:Tomcat一旦发现多了一个web应用APP.war包,默认会自动把它解压缩,加载并启动起来
    • 手动部署
      • 冷部署:将webapp放到指定目录,才去启动Tomcat服务
      • 热部署:Tomcat服务不停止,需要依赖manager、ant脚本、tcd(tomcat client deployer)等工具
  • 反部署 undeploy:停止webapp运行,并从JVM上清除已经加载的类,从Tomcat应用目录中移除部署的文件
  • 启动 start:启用 webapp 能够访问
  • 停止 stop:禁用 webapp 不能访问,不能提供服务,但是JVM并不清除它

部署WebApp的目录结构

常见开发项目目录组成

#目录结构一般由开发用工具自动生成,以下模拟生成相关目录
mkdir projects/myapp/{WEB-INF,META-INF,classes,lib} -pv
mkdir: 已创建目录 "projects"
mkdir: 已创建目录 "projects/myapp"
mkdir: 已创建目录 "projects/myapp/WEB-INF"
mkdir: 已创建目录 "projects/myapp/META-INF"
mkdir: 已创建目录 "projects/myapp/classes"
mkdir: 已创建目录 "projects/myapp/lib

#常见应用首页,内容就用前面的test.jsp内部
vi projects/myapp/index.jsp

#手动复制项目目录到webapps目录下去
cp -r projects/myapp/ /usr/local/tomcat/webapps/

#注意权限和属性
chown -R tomcat.tomcat /usr/local/tomcat/webapps/myapp

#访问http://YourIP:8080/myapp/

实战案例:手动的应用部署

部署主页目录下的应用WebApp
[root@centos8 tomcat]#vim webapps/ROOT/test.jsp
[root@centos8 tomcat]#cat webapps/ROOT/test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<%
out.println("hello jsp");
%>
<br>
<%=request.getRequestURL()%>
</body>	
</html>

[root@centos8 tomcat]#curl http://127.0.0.1:8080/test.jsp
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
	<title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
hello jsp
<br>
http://127.0.0.1:8080/test.jsp
</body>
</html>

[root@centos8 tomcat]#tree work/Catalina/localhost/ROOT/
work/Catalina/localhost/ROOT/
└── org
	└── apache
		└── jsp
            ├── test_jsp.class
            └── test_jsp.java
部署一个子目录的应用WebApp
[root@centos8 tomcat]#pwd
/usr/local/tomcat
[root@centos8 tomcat]#mkdir webapps/app1/

#利用之前实验的文件生成新应用
[root@centos8 tomcat]#cp -p webapps/ROOT/test.jsp webapps/app1/
[root@centos8 tomcat]#chown -R tomcat.tomcat webapps/app1/
[root@centos8 tomcat]#tree webapps/app1/
webapps/testapp1/
└── test.jsp

[root@centos8 tomcat]#curl http://127.0.0.1:8080/app1/test.jsp
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
	<title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
hello jsp
<br>
<%=request.getRequestURL()%>
</body>
</html>

[root@centos8 tomcat]#tree work/Catalina/localhost/app1/
work/Catalina/localhost/app1/
└── org
    └── apache
    	└── jsp
            ├── test_jsp.class
            └── test_jsp.java
            
#删除应用
[root@centos8 tomcat]#rm -rf webapps/app1/
[root@centos8 tomcat]#ls webapps/
docs examples host-manager manager ROOT
[root@centos8 tomcat]#ls work/Catalina/localhost/
docs examples host-manager manager ROOT

实战案例:自动的应用部署war包

制作应用的war包文件
[root@centos8 ~]#ls /data/app2/
test.html test.jsp
[root@centos8 ~]#cat /data/app2/test.html
<h1>This is test html </h1>
[root@centos8 ~]#cat /data/app2/test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
		pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<%
out.println("test jsp");
%>
<br>
<%=request.getRequestURL()%>
</body>
</html>
[root@centos8 ~]#cd /data/app2/

#生成war包文件app2.war,此文件的名称决定了tomcat子目录的名称
[root@centos8 app2]#jar cvf /data/app2.war *
added manifest
adding: test.html(in = 28) (out= 27)(deflated 3%)
adding: test.jsp(in = 329) (out= 275)(deflated 16%)
[root@centos8 app2]#cd /data/app2/
[root@centos8 app2]#ls
test.html test.jsp
[root@centos8 app2]#cd /data/
[root@centos8 data]#ls
app2 app2.war
[root@centos8 data]#file app2.war
app2.war: Java archive data (JAR)
[root@centos8 data]#chown tomcat.tomcat /data/app2.war
自动应用部署上面的war包
[root@centos8 tomcat]#pwd
/usr/local/tomcat

[root@centos8 tomcat]#ls webapps/
docs examples host-manager manager ROOT
[root@centos8 tomcat]#ls work/Catalina/localhost/
docs examples host-manager manager ROOT
[root@centos8 tomcat]#cp -p /data/app2.war webapps/

#再次查看,tomcat将app2.war自动解压缩
[root@centos8 tomcat]#ll webapps/
total 8
drwxr-x--- 15 tomcat tomcat 4096 Feb 9 11:02 docs
drwxr-x--- 6 tomcat tomcat 83 Feb 9 11:02 examples
drwxr-x--- 5 tomcat tomcat 87 Feb 9 11:02 host-manager
drwxr-x--- 5 tomcat tomcat 103 Feb 9 11:02 manager
drwxr-x--- 3 tomcat tomcat 300 Feb 9 19:59 ROOT
drwxr-x--- 3 tomcat tomcat 55 Feb 9 20:14 app2
-rw-r--r-- 1 tomcat tomcat 862 Feb 9 20:05 app2.war
[root@centos8 tomcat]#ll webapps/app2
total 8
drwxr-x--- 2 tomcat tomcat 44 Feb 9 20:14 META-INF
-rw-r----- 1 tomcat tomcat 28 Feb 9 20:03 test.html
-rw-r----- 1 tomcat tomcat 329 Aug 30 02:30 test.jsp

#work目录会自动生成对应的app2的子目录,但目录内无内容
[root@centos8 tomcat]#tree work/Catalina/localhost/app2/
work/Catalina/localhost/app2/

#访问jsp文件后,tomcat会自动将jsp转换和编译生成work目录下对应的java和class文件
[root@centos8 tomcat]#curl http://127.0.0.1:8080/app2/test.jsp

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
hello jsp
</body>
</html>

[root@centos8 tomcat]#tree work/Catalina/localhost/app2/
work/Catalina/localhost/app2/
└── org
	└── apache
		└── jsp
            ├── test_jsp.class
            └── test_jsp.java
            
[root@centos8 tomcat]#curl http://127.0.0.1:8080/app2/test.html
<h1>This is test html </h1>
[root@centos8 tomcat]#tree work/Catalina/localhost/app2/
work/Catalina/localhost/estapp2/
└── org
	└── apache
		└── jsp
            ├── test_jsp.class
            └── test_jsp.java
            
#自动删除(反部署)
#[root@centos8 tomcat]#rm -f webapps/app2.war
[root@centos8 tomcat]#ls webapps/
docs examples host-manager manager ROOT app2
#过几秒再查看,发现app2目录也随之删除
[root@centos8 tomcat]#ls webapps/
docs examples host-manager manager ROOT
[root@centos8 tomcat]#ls webapps/
docs examples host-manager manager ROOT
[root@centos8 tomcat]#ls work/Catalina/localhost/
docs examples host-manager manager ROOT

实站案例: 部署基于JAVA的博客系统 JPress

JPress 是一个使用Java开发的类似WordPress的产品的建站神器,目前已有超过10万+网站使用 JPress搭建,其中包括多个政府机构,200+上市公司,中科院、红十字会等。

和JPress 相类似的基于 java 开发的博客系统还有Halo, zrlog等

开源协议: LGPL-3.0
官方网站: http://www.jpress.io/
当前 Jpress 支持Java8和11

注意: Jpress 程序的Bug,必须部署到网站根目录下才能正常使用

[root@centos8 ~]#cd /usr/local/tomcat/webapps/
[root@centos8 webapps]#ls
docs examples host-manager jpress-v3.2.1.war manager ROOT

#自动解压缩生成jpress-v3.2.1目录
[root@centos8 webapps]#ls
docs examples host-manager jpress-v3.2.1 jpress-v3.2.1.war manager ROOT

#生成软链接
[root@centos8 webapps]#ln -s jpress-v3.2.1 jpress
[root@centos8 webapps]#ls
docs examples host-manager jpress jpress-v3.2.1 jpress-v3.2.1.war manager
ROOT
[root@centos8 webapps]#

#准备数据库和用户授权
[root@centos8 ~]#yum -y install mysql-server
[root@centos8 ~]#systemctl enable --now mysqld
[root@centos8 ~]#mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.17 Source distribution
mysql> create database jpress;

#MySQL8.0需要指定插件
mysql> create user jpress@'10.0.0.%' identified with mysql_native_password by '123456';
#MySQL5.7之前无需指定插件
mysql> create user jpress@'10.0.0.%' identified by '123456';
mysql> grant all on jpress.* to jpress@'10.0.0.%';

上传的图片存放路径

[root@centos8 webapps]#tree jpress/attachment/
jpress/attachment/
└── 20210110
	└── 2169440a4e75459d8a420f4b245565d4.jpg
1 directory, 1 file

实战案例: 部署基于JAR包的博客系统 Halo

Halo 是一款现代化的基于JAVA实现的博客/CMS系统

Halo 官网: https://halo.run/
Halo 部署: https://docs.halo.run/install/linux
Docker 部署: https://docs.halo.run/install/docker
Halo 下载: https://dl.halo.run/

范例: 部署 Halo 博客系统

#注意:运行当前版本Halo的最低依赖要求为 JRE 11,目前介绍两种 Linux 发行版的安装方式,均为OpenJRE,不推荐 Oracle 版本。
[root@ubuntu1804 ~]#apt -y install openjdk-11-jdk
[root@ubuntu1804 ~]#mkdir /apps

#最新版
[root@ubuntu2204 ~]#wget https://dl.halo.run/release/halo-1.6.0.jar -O /opt/halo.jar
#旧版
[root@ubuntu1804 ~]#wget https://dl.halo.run/release/halo-1.4.11.jar -O /apps/halo.jar

或者
[root@ubuntu1804 ~]#curl -L https://github.com/halo- dev/halo/releases/download/v1.4.11/halo-1.4.11.jar --output /apps/halo.jar

#运行Halo
[root@ubuntu1804 ~]#java -jar /apps/halo.jar --server.port=80

范例: docker 启动 halo

[root@ubuntu1804 ~]#docker run -it -d --name halo -p 8090:8090 -v ~/.halo:/root/.halo --restart=always halohub/halo

基于WEB的管理Server status和Manager APP实现应用部署

tomcat 提供了基于WEB的管理页面,默认由 tomcat-admin-webapps.noarch包提供相关文件

实现WEB的管理Server status和Manager APP

打开浏览器可以访问tomcat管理的默认管理页面,点击下图两个按钮都会出现下面提示403的错误提示

图片-cJhyweBiqVkDfUoLZQmeZQwjNMzcBeGM.png

默认的管理页面被禁用,启用方法如下

  • 修改webapps/manager/META-INF/context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="false" privileged="true" >
	<Valve className="org.apache.catalina.valves.RemoteAddrValve"
		allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
	<Manager sessionAttributeValueClassNameFilter="java\.lang\.
(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreve
ntionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

查看正则表达式就知道是本地访问了,由于当前访问地址是192.168.x.x,可以修改正则表达式为

allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192\.168\.\d+\.\d+"

范例:

[root@centos8 tomcat]#vim webapps/manager/META-INF/context.xml
	<Context antiResourceLocking="false" privileged="true" >
		<Valve className="org.apache.catalina.valves.RemoteAddrValve"
			allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|10\.0\.0\.\d+" />
	<Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>
#修改WebApp的配置无需重启服务即可生效
  • 修改conf/conf/tomcat-users.xml
[root@centos8 tomcat]#ls conf/
Catalina context.xml logging.properties tomcat-
users.xml
catalina.policy jaspic-providers.xml server.xml tomcat-
users.xsd
catalina.properties jaspic-providers.xsd tomcat.conf web.xml

#查看配置信息
[root@centos8 tomcat]#cat conf/server.xml
<GlobalNamingResources>
	<!-- Editable user database that can also be used by
		UserDatabaseRealm to authenticate users
	-->
	<Resource name="UserDatabase" auth="Container"
				type="org.apache.catalina.UserDatabase"
				description="User database that can be updated and saved"
				factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
				pathname="conf/tomcat-users.xml" /> #由此文件指定授权用户信息
	</GlobalNamingResources>
  • 用户认证,配置文件是conf/tomcat-users.xml。打开tomcat-users.xml,我们需要一个角色manager-gui。
[root@centos8 tomcat]#vim conf/tomcat-users.xml
<tomcat-users xmlns="http://tomcat.apache.org/xml"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
				xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
				version="1.0">
    #加下面两行,指定用户和密码
    <role rolename="manager-gui"/>
    <user username="admin" password="123456" roles="manager-gui"/>
    </tomcat-users>
#修改全局配置文件需要重启服务生效
[root@centos8 tomcat]#systemctl restart tomcat
  • 再次通过浏览器访问两个按钮Server Status和Manager App,可以看到管理界面,输入前面的用户和密码进行登录
[root@centos8 ~]#links -dump http://admin:123456@10.0.0.100:8080/manager/status
基于WEB应用程序管理器实现APP的部署

Web 应用程序管理界面可以实现以下功能

Applications 应用程序管理,可以启动、停止、重加载、反部署、清理过期session

Deploy 可以热部署,也可以部署war文件。

方式1: 指定目录部署软件

[root@centos8 ~]#mkdir -p /data/myapp/
[root@centos8 ~]#echo /data/myapp/index.html > /data/myapp/index.html

#按下面信息添写,实现下面链接的访问
http://10.0.0.8:8080/test1/
Context Path (required): 指定通过浏览器访问的虚拟目录
WAR or Directory URL:指定真正存放文件的实际磁盘目录路径
#自动将/data/myapp目录下的数据复制到webapps/test1下面
[root@centos8 ~]#tree /usr/local/tomcat/webapps/test1/
/usr/local/tomcat/webapps/test1/
└── index.html

[root@centos8 ~]#cat /usr/local/tomcat/webapps/test1/index.html
/data/myapp/index.html

方式2: 部署war包文件

常见配置详解

端口8005/tcp 安全配置管理

在conf/server.xml 有以下内容

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
	<Service name="Catalina">
		<Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
		<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
        
		<Engine name="Catalina" defaultHost="localhost">
			<Host name="localhost" appBase="webapps"
                  unpackWARs="true" autoDeploy="true">
			</Host>
		</Engine>
	</Service>
</Server>
<Server port="8005" shutdown="SHUTDOWN">

8005是Tomcat的管理端口,默认监听在127.0.0.1上。无需验证就可发送SHUTDOWN (大小写敏感)这个字符串,tomcat接收到后就会关闭此Server。

此管理功能建议禁用,可将SHUTDOWN改为一串猜不出的字符串实现

或者port修改成 0, 会使用随机端口,如:36913

port设为-1等无效端口,将关闭此功能,注意:-2等不支持

此行不能被注释,否则无法启动tomcat服务

范例:

<Server port="8005" shutdown="44ba3c71d57f494992641b258b965f28">

范例:修改8005/tcp端口管理命令

[root@centos8 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port
Peer Address:Port
LISTEN 0 128 0.0.0.0:22
0.0.0.0:*
LISTEN 0 100 *:8080
*:*
LISTEN 0 128 [::]:22
[::]:* LISTEN 0 1
[::ffff:127.0.0.1]:8005 *:* LISTEN 0
100 *:8009
*:*

[root@centos8 ~]#telnet 127.0.0.1 8005
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
SHUTDOWN #执行命令关闭tomcat
Connection closed by foreign host.

[root@centos8 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port
Peer Address:Port
LISTEN 0 128 0.0.0.0:22
0.0.0.0:*
LISTEN 0 128 [::]:22
[::]:*

[root@centos8 tomcat]#vim conf/server.xml
<Server port="8005" shutdown="ayaka">
[root@centos8 tomcat]#systemctl start tomcat
[root@centos8 tomcat]#telnet 127.0.0.1 8005
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
SHUTDOWN
Connection closed by foreign host.
[root@centos8 tomcat]#ss -ntl
State Recv-Q Send-Q Local Address:Port
Peer Address:Port
LISTEN 0 128 0.0.0.0:22
0.0.0.0:*
3.4.5.2 显示指定的http服务器版本信息
默认不显示tomcat的http的Server头信息, 可以指定tomcat的http的Server头信息为相应的值
范例:
LISTEN 0 100 *:8080
*:*
LISTEN 0 128 [::]:22
[::]:*
LISTEN 0 1 [::ffff:127.0.0.1]:8005
*:*
LISTEN 0 100 *:8009
*:*
root@centos8 tomcat]#telnet 127.0.0.1 8005
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
ayaka
Connection closed by foreign host.
[root@centos8 tomcat]#ss -ntl
State Recv-Q Send-Q Local Address:Port
Peer Address:Port
LISTEN 0 128 0.0.0.0:22
0.0.0.0:*
LISTEN 0 128 [::]:22
[::]:*
[root@centos8 tomcat]#

显示指定的http服务器版本信息

默认不显示tomcat的http的Server头信息, 可以指定tomcat的http的Server头信息为相应的值

#conf/server.xml
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" Server="SOME STRING"/>

范例

[root@centos8 ~]#curl -I 127.0.0.1:8080
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 17 Jul 2020 08:32:52 GMT

#修改配置,指定想显示的tomcat版本
[root@centos8 ~]#vim /usr/local/tomcat/conf/server.xml
......
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" Server="aServer"/>
......

[root@centos8 ~]#systemctl restart tomcat
[root@centos8 ~]#curl 127.0.0.1:8080 -I
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 17 Jul 2020 08:34:17 GMT
Server: aServer

其它配置

conf/server.xml中可以配置service,connector, Engine,Host等

  • service配置

一般情况下,一个Server实例配置一个Service,name属性相当于该Service的ID。

<Service name="Catalina">
  • 连接器配置
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

redirectPort,如果访问HTTPS协议,自动转向这个连接器。但大多数时候,Tomcat并不会开启HTTPS,因为Tomcat往往部署在内部,HTTPS性能较差

  • 引擎配置
<Engine name="Catalina" defaultHost="localhost">
  • defaultHost 配置

defaultHost指向内部定义某虚拟主机。缺省虚拟主机可以改动,默认localhost

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

多虚拟主机配置

多虚拟主机配置说明
  • name 必须是主机名,用主机名来匹配
  • appBase 当前主机的网页根目录,是相对于$CATALINA_HOME ,也可以使用绝对路径
  • unpackWARs 是否自动解压war格式
  • autoDeploy 热部署,自动加载并运行应用

虚拟主机配置过程

  • 再添加和配置一个新的虚拟主机,并将myapp部署到/data/webapps目录下
vim conf/server.xml
#在文件最后面增加下面内容
<Host name="web1.ayaka.org" appBase="/data/webapps/" unpackWARs="True" autoDeploy="false">
    
#虚拟主机专有访问日志
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="web1_access_log" suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>

#以下行是自带的不需要修改
</Engine>
</Service>
</Server>

#或者如果不加日志也可以用下面简化写法
<Host name="web1.ayaka.org" appBase="/data/webapps/" unpackWARs="True" autoDeploy="false"/>


  • 准备虚拟主机的数据目录
常见虚拟主机根目录
# mkdir /data/webapps/ROOT -pv
# chown -R tomcat.tomcat /data/webapps
# echo web1.ayaka.org > /data/webapps/ROOT/index.html
  • 测试

刚才在虚拟主机中主机名定义node1.ayaka.org,所以需要主机在本机手动配置一个域名解析

如果是windows,修改在C:\Windows\System32\drivers\etc下的hosts文件,需要管理员权限。

使用http://web1.ayaka.org:8080/访问查看

实战案例:tomcat实现多虚拟主机
[root@centos8 tomcat]#pwd
/usr/local/tomcat
[root@centos8 tomcat]#vim conf/server.xml
[root@centos8 tomcat]#tail conf/server.xml
				pattern="%h %l %u %t &quot;%r&quot; %s %b" />
		</Host>	
#添加了以下行
		<Host name="node1.ayaka.org" appBase="/data/webapps1/" unpackWARs="true" autoDeploy="true">
			<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
				prefix="node1_access_log" suffix=".txt"
                   pattern="%h %l %u %t &quot;%r&quot; %s %b" />
            
		</Host>		
		<Host name="node2.ayaka.org" appBase="/data/webapps2/" unpackWARs="true" autoDeploy="true">
			<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
				prefix="node2_access_log" suffix=".txt"
                   pattern="%h %l %u %t &quot;%r&quot; %s %b" />
		</Host>
	</Engine>
  </Service>
</Server>

#对每个虚拟主机,准备数据
[root@centos8 ~]#mkdir /data/webapps{1,2}/ROOT -pv
mkdir: created directory '/data/webapps1/ROOT'
mkdir: created directory '/data/webapps2/ROOT'
[root@centos8 ~]#cat /data/webapps1/ROOT/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<br>
<%=request.getRequestURL()%>
</body>
</html>

[root@centos8 ~]#cat /data/webapps2/ROOT/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<br>
<%=request.getRequestURL()%>
</body>
</html>
[root@centos8 ~]#

#设置权限
[root@centos8 ~]#chown -R tomcat.tomcat /data/webapps{1,2}/

#准备虚拟主机的名称解析
[root@centos8 ~]#cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
centos8.localdomain
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.8 node1.ayaka.org node2.ayaka.org

[root@centos8 ~]#curl http://node1.ayaka.org:8080/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
http://node1.ayaka.org:8080/
</body>
</html>

[root@centos8 ~]#curl http://node2.ayaka.org:8080/

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
http://node2.ayaka.org:8080/
</body>
</html>
实战案例:修改tomcat实现多虚拟主机的端口为80
[root@centos8 ~]#vim /usr/local/tomcat/conf/server.xml
<Connector port="80" protocol="HTTP/1.1"
				connectionTimeout="20000"
				redirectPort="8443" />
				
#注意: 因为以tomcat用户运行,不能直接使用1024以下的端口,需要修改tomcat的运行身份,否则会出现下面错误
[root@centos8 ~]#tail -f /usr/local/tomcat/logs/catalina.out
Caused by: java.net.SocketException: Permission denied

[root@centos8 ~]#vim /lib/systemd/system/tomcat.service
[Service]
.....
#User=tomcat
#Group=tomcat
[root@centos8 ~]#systemctl daemon-reload
[root@centos8 ~]#systemctl restart tomcat

基于web方式的Host Manager虚拟主机管理

可以通过tomcat的管理页面点下面Host Manager按钮进入管理虚拟主机的页面

默认Host Manager 管理页被禁用,会出现下面提示,解决方法类似于上面

允许本机访问

配置如下

[root@centos8 tomcat]#vim conf/tomcat-users.xml
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
    <role rolename="manager-gui"/> #3.4.4.6添加的内容
    <role rolename="admin-gui" /> #添加新的role
    <user username="admin" password="123456" roles="manager-gui,admin-gui"/> #再加新role
	
</tomcat-users>
[root@centos8 tomcat]#systemctl restart tomcat

重启Tomcat后,点击"Host Manager"按钮

允许远程主机访问

但通过远程访问地址仍无法访问Host Manager管理页面

默认无法通过网络远程访问Host Manager管理页面,默认会出现403界面

[root@centos8 tomcat]#vim webapps/host-manager/META-INF/context.xml
<Context antiResourceLocking="false" privileged="true" >
	<Valve className="org.apache.catalina.valves.RemoteAddrValve"
			allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|10\.0\.0\.\d+" />
	<Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

无需重启服务,直接访问,输入前面的用户和密码,即可登录成功

创建新的虚拟主机

可以管理虚拟主机

#创建虚拟主机前,必须先创建相关目录,否则创建虚拟机不成功
[root@centos8 ~]#mkdir /data/node1/ROOT/
[root@centos8 ~]#echo node1.aya.org > /data/node1/ROOT/index.html
[root@centos8 ~]#chown -R tomcat.tomcat /data/node1/

Context 配置

Centext 配置方式

Context作用:

  • 路径映射:将url映射至指定路径,而非使用appBase下的物理目录,实现虚拟目录功能
  • 应用独立配置,例如单独配置应用日志、单独配置应用访问控制
#映射指定路径
<Context path="/test" docBase="/data/test" reloadable="true" />

#映射站点的根目录
<Context path="/" docBase="/data/website" reloadable="true" />

#还可以添加日志等独立的配置
<Context path="/test" docBase="/data/test" reloadable="true" >
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_test_log" suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Context>

说明:

  • path:指的是访问的URL路径,如果path与appBase下面的子目录同名,context的docBase路径优先级更高
  • docBase:可以是磁盘文件的绝对路径,也可以是相对路径(相对于Host的appBase)
  • reloadable:true表示如果WEB-INF/classes或META-INF/lib目录下.class文件有改动,就会将WEB应用重新加载。生产环境中,建议使用false来禁用。

Centext实现过程

  • 将~/projects/myapp/下面的项目文件复制到/data/下,可以修改一下index.jsp 区别一下
# cp -r ~/projects/myapp /data/myapp-v1
# vim /data/myappv1/index.jsp
# cd /data
# ln -sv myapp-v1 test

**注意:**这里特别使用了软链接,原因方便后期版升级或回滚,如是是版本升级,需要将软链接指向myappv2,重新启动。如果新版上线后,出现问题,重新修改软链接到上一个版本的目录,并重启,就可以实现回滚

  • 修改conf/server.xml设置context

Tomcat的配置文件server.xml中修改如下,重启Tomcat生效

	<Host name="node1.ayaka.org" appBase="/data/webapps"
      	unpackWARs="true" autoDeploy="true" >
		<Context path="/test" docBase="/data/test" reloadable="true" />
	</Host>
Valve组件

日志格式说明

http://tomcat:8080/docs/config/valve.html#Access_Logging

%a - Remote IP address. See also %{xxx}a below.
%A - Local IP address
%b - Bytes sent, excluding HTTP headers, or '-' if zero
%B - Bytes sent, excluding HTTP headers
%h - Remote host name (or IP address if enableLookups for the connector is
false)
%H - Request protocol
%l - Remote logical username from identd (always returns '-')
%m - Request method (GET, POST, etc.)
%p - Local port on which this request was received. See also %{xxx}p below.
%q - Query string (prepended with a '?' if it exists)
%r - First line of the request (method and request URI)
%s - HTTP status code of the response
%S - User session ID
%t - Date and time, in Common Log Format
%u - Remote user that was authenticated (if any), else '-' (escaped if required)
%U - Requested URL path
%v - Local server name
%D - Time taken to process the request in millis. Note: In httpd %D is
microseconds. Behaviour will be aligned to httpd in Tomcat 10 onwards.
%T - Time taken to process the request, in seconds. Note: This value has
millisecond resolution whereas in httpd it has second resolution. Behaviour will
be align to httpd in Tomcat 10 onwards.
%F - Time taken to commit the response, in milliseconds
%I - Current request thread name (can compare later with stacktraces)
%X - Connection status when response is completed:
X = Connection aborted before the response completed.
+ = Connection may be kept alive after the response is sent.
- = Connection will be closed after the response is sent.

valve(阀门)组件可以定义日志

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_access_log" suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

valve存在多种类型:

定义访问日志:org.apache.catalina.valves.AccessLogValve
定义访问控制:org.apache.catalina.valves.RemoteAddrValve

示例:

<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny="10\.0\.0\.\d+"/>
实战案例

范例:虚拟主机上利用context实现虚拟目录

#在前面范例的基础上实现,继续创建node1.ayaka.org虚拟主机下的物理子目录
[root@centos8 ~]#mkdir /data/webapps1/app1/
[root@centos8 ~]#echo /data/webapps1/app1/index.html > /data/webapps1/app1/index.html
[root@centos8 ~]#curl http://node1.ayaka.org:8080/app1/
/data/webapps1/app1/index.html

#利用context实现node1.ayaka.org虚拟主机下的虚拟子目录
[root@centos8 tomcat]#vim conf/server.xml
[root@centos8 tomcat]#tail conf/server.xml
    </Host>
    <Host name="node1.ayaka.org" appBase="/data/webapps1">
    #加下面六行
    <Context path="/app1" docBase="/data/app1" reloadable="true" >
    	<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    			prefix="node1.ayaka.org_app1" suffix=".log"
    			pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    	<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="10\.0\.0\.7"/>
    </Context>
    
    </Host>
    <Host name="node2.ayaka.org" appBase="/data/webapps2">
    </Host>
    </Engine>
    </Service>
</Server>
[root@centos8 tomcat]#systemctl restart tomcat

#因数据没有准备好,出现下面错误
[root@centos8 tomcat]#curl http://node1.ayaka.org:8080/app1/
curl: (7) Failed to connect to node1.ayaka.org port 8080: Connection refused

#准备数据目录
[root@centos8 tomcat]#mkdir /data/app1-v1
[root@centos8 tomcat]#echo /data/app1-v1/index.html > /data/app1-v1/index.html
[root@centos8 tomcat]#ln -s /data/app1-v1/ /data/app1
[root@centos8 tomcat]#curl http://node1.ayaka.org:8080/app1/
curl: (7) Failed to connect to node1.ayaka.org port 8080: Connection refused

#数据目录准备好,还需要重新启动服务,才能访问
[root@centos8 tomcat]#systemctl restart tomcat
[root@centos8 tomcat]#curl http://node1.ayaka.org:8080/app1/
/data/app1-v1/index.html
[root@centos7 ~]#curl -I http://node1.ayaka.org:8080/app1/
HTTP/1.1 403
Content-Type: text/html;charset=utf-8
Content-Language: en
Transfer-Encoding: chunked
Date: Tue, 14 Jul 2020 06:48:54 GMT

#可以看到此目录单独的访问日志
[root@centos8 ~]#cat /usr/local/tomcat/logs/node1.ayaka.org_app1.2025-07-14.log
10.0.0.8 - - [14/Jul/2025:14:36:01 +0800] "GET /app1/ HTTP/1.1" 200 330
10.0.0.7 - - [14/Jul/2025:14:48:07 +0800] "GET /app1/ HTTP/1.1" 403 61

范例: 基于前面环境,实现软件升级和回滚功能

#升级版本
[root@centos8 tomcat]#mkdir /data/app1-v2
[root@centos8 tomcat]#echo /data/app1-v2/index.html > /data/app1-v2/index.html
[root@centos8 tomcat]#rm -f /data/app1

#删除软链接,仍然可以访问旧版本
[root@centos8 tomcat]#curl http://node1.ayakaorg:8080/app1/
/data/app1-v1/index.html

#重新服务后,出现错误
[root@centos8 tomcat]#systemctl restart tomcat
[root@centos8 tomcat]#curl http://node1.ayakaorg:8080/app1/
curl: (7) Failed to connect to node1.ayakaorg port 8080: Connection refused

#新建软链接,指向新版,仍需重启服务才生效
[root@centos8 tomcat]#ln -s /data/app1-v2/ /data/app1
[root@centos8 tomcat]#curl http://node1.ayakaorg:8080/app1/
curl: (7) Failed to connect to node1.ayakaorg port 8080: Connection refused
[root@centos8 tomcat]#systemctl restart tomcat
[root@centos8 tomcat]#curl http://node1.ayakaorg:8080/app1/
/data/app1-v2/index.html

#软件降级或回滚
[root@centos8 tomcat]#rm -f /data/app1
[root@centos8 tomcat]#ln -s /data/app1-v1/ /data/app1
[root@centos8 tomcat]#systemctl restart tomcat
[root@centos8 tomcat]#curl http://node1.ayakaorg:8080/app1/
/data/app1-v1/index.html

评论