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的错误提示

默认的管理页面被禁用,启用方法如下
- 修改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 "%r" %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 "%r" %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 "%r" %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 "%r" %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 "%r" %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 "%r" %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 "%r" %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