Tomcat使用入门
Tomcat是一个免费的开放源代码的Web应用服务器,具有处理HTML静态资源页面的功能,同时它还是一个Servlet和JSP的容器。Tomcat于1999年发布,初始版本为3.0,实现了Servlet2.2和JSP1.1的规范。
Tomcat的核心分为3个部分:
- Web容器:负责处理静态页面;
- JSP容器:把JSP页面翻译为一般的Servlet
- Catalina:是一个servlet容器,用于处理servlet
部署服务
# 安装JDK
[root@tomcat]dnf install -y java-17-openjdk java-17-openjdk-devel
[root@tomcat]alternatives --config java
There is 1 program that provides 'java'.
Selection Command
-----------------------------------------------
*+ 1 java-17-openjdk.x86_64 (/usr/lib/jvm/java-17-openjdk-17.0.6.0.9-0.3.ea.el8.x86_64/bin/java)
[root@tomcat]alternatives --config javac
There is 1 program that provides 'javac'.
Selection Command
-----------------------------------------------
*+ 1 java-17-openjdk.x86_64 (/usr/lib/jvm/java-17-openjdk-17.0.6.0.9-0.3.ea.el8.x86_64/bin/javac)
Enter to keep the current selection[+], or type selection number: 1
# 验证JDK
[root@tomcat]java --version
openjdk 17.0.6-ea 2023-01-17 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.6.0.9-0.3.ea.el8) (build 17.0.6-ea+9-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.6.0.9-0.3.ea.el8) (build 17.0.6-ea+9-LTS, mixed mode, sharing)
# 创建java程序并执行
cat > java_test.java << EOF
class java_test {
public static void main(String[] args) {
System.out.println("Hello Java World !");
}
}
EOF
# 执行java程序
[root@tomcat]java java_test.java
Hello Java World !
# 安装Tomcat 10
# 下载
[root@tomcat] curl -O https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.13/bin/apache-tomcat-10.1.13.tar.gz
[root@tomcat] tar zxvf apache-tomcat-10.1.13.tar.gz
# 移动执行文件到目录
[root@tomcat]mv apache-tomcat-10.1.13 /usr/libexec/tomcat
# 新增用户
[root@tomcat]useradd -M -d /usr/libexec/tomcat/ tomcat
# 配置权限
[root@tomcat]chown -R tomcat:tomcat /usr/libexec/tomcat/
# 创建服务配置文件
[root@tomcat]cat > /usr/lib/systemd/system/tomcat.service <<EOF
[Unit]
Description=Apache Tomcat 10
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/libexec/tomcat/bin/startup.sh
ExecStop=/usr/libexec/tomcat/bin/shutdown.sh
RemainAfterExit=yes
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
EOF
# 重新加载服务
[root@tomcat]systemctl daemon-reload
[root@tomcat]systemctl enable --now tomcat.service
Created symlink /etc/systemd/system/multi-user.target.wants/tomcat.service →
[root@tomcat]netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 4601/java
tcp6 0 0 :::8080 :::* LISTEN 4601/java
# 配置防火墙
[root@tomcat] firewall-cmd --add-port=8080/tcp --permanent
[root@tomcat] firewall-cmd --reload
# 测试web-server
[root@tomcat]mkdir /usr/libexec/tomcat/webapps/ROOT/WEB-INF/classes
[root@tomcat]chown -R tomcat:tomcat /usr/libexec/tomcat/
[root@tomcat]cat > /usr/libexec/tomcat/webapps/ROOT/WEB-INF/classes/daytime.java <<EOF
import java.io.*;
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.util.Calendar;
public class daytime extends HttpServlet {
public void doGet(HttpServletRequest request
,HttpServletResponse response)
throws IOException, ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Calendar cal = Calendar.getInstance();
out.println("<html>\n<head>\n<title>DayTime</title>\n</head>\n<body>");
out.println("<div style=\"font-size: 40px; text-align: center; font-weight: bold\">");
out.println(cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH) + 1) + "/" +
cal.get(Calendar.DATE) + " " + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE));
out.println("</div>\n</body>\n</html>");
}
}
EOF
# 运行java程序
[root@tomcat]javac -classpath /usr/libexec/tomcat/lib/servlet-api.jar /usr/libexec/tomcat/webapps/ROOT/WEB-INF/classes/daytime.java
[root@tomcat]cat > /usr/libexec/tomcat/webapps/ROOT/WEB-INF/web.xml <<EOF
<servlet>
<servlet-name>daytime</servlet-name>
<servlet-class>daytime</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>daytime</servlet-name>
<url-pattern>/daytime</url-pattern>
</servlet-mapping>
EOF
# 网页验证
[root@tomcat]lynx http://127.0.0.1:8080/daytime
2022/12/23 13:23
配置管理
目录结构
[root@tomcat]tree -d apache-tomcat-10.1.13
apache-tomcat-10.1.13
├── bin # 服务启动、停止等相关程序和文件
├── conf # 配置文件
├── lib # 库目录
├── logs # 日志目录
├── temp # 临时文件目录
├── webapps # 应用程序部署目录
│ ├── docs
│ │ ├── annotationapi
│ │ ├── api
│ │ ├── appdev
│ │ │ └── sample
│ │ │ ├── docs
│ │ │ ├── src
│ │ │ │ └── mypackage
│ │ │ └── web
│ │ │ ├── images
│ │ │ └── WEB-INF
│ │ ├── architecture
│ │ │ ├── requestProcess
│ │ │ └── startup
│ │ ├── config
│ │ ├── elapi
│ │ ├── images
│ │ │ └── fonts
│ │ ├── jaspicapi
│ │ ├── jspapi
│ │ ├── META-INF
│ │ ├── servletapi
│ │ ├── tribes
│ │ ├── WEB-INF
│ │ │ └── jsp
│ │ └── websocketapi
│ ├── examples
│ │ ├── jsp
│ │ │ ├── async
│ │ │ ├── cal
│ │ │ ├── checkbox
│ │ │ ├── colors
│ │ │ ├── dates
│ │ │ ├── error
│ │ │ ├── forward
│ │ │ ├── images
│ │ │ ├── include
│ │ │ ├── jsp2
│ │ │ │ ├── el
│ │ │ │ ├── jspattribute
│ │ │ │ ├── jspx
│ │ │ │ ├── misc
│ │ │ │ ├── simpletag
│ │ │ │ └── tagfiles
│ │ │ ├── jsptoserv
│ │ │ ├── num
│ │ │ ├── security
│ │ │ │ └── protected
│ │ │ ├── sessions
│ │ │ ├── simpletag
│ │ │ ├── snp
│ │ │ ├── tagplugin
│ │ │ └── xml
│ │ ├── META-INF
│ │ ├── servlets
│ │ │ ├── images
│ │ │ └── nonblocking
│ │ ├── WEB-INF
│ │ │ ├── classes
│ │ │ │ ├── async
│ │ │ │ ├── cal
│ │ │ │ ├── checkbox
│ │ │ │ ├── colors
│ │ │ │ ├── compressionFilters
│ │ │ │ ├── dates
│ │ │ │ ├── error
│ │ │ │ ├── examples
│ │ │ │ ├── filters
│ │ │ │ ├── http2
│ │ │ │ ├── jsp2
│ │ │ │ │ └── examples
│ │ │ │ │ ├── el
│ │ │ │ │ └── simpletag
│ │ │ │ ├── listeners
│ │ │ │ ├── nonblocking
│ │ │ │ ├── num
│ │ │ │ ├── sessions
│ │ │ │ ├── trailers
│ │ │ │ ├── util
│ │ │ │ ├── validators
│ │ │ │ └── websocket
│ │ │ │ ├── chat
│ │ │ │ ├── drawboard
│ │ │ │ │ └── wsmessages
│ │ │ │ ├── echo
│ │ │ │ └── snake
│ │ │ ├── jsp
│ │ │ ├── lib
│ │ │ └── tags
│ │ └── websocket
│ ├── host-manager
│ │ ├── css
│ │ ├── images
│ │ ├── META-INF
│ │ └── WEB-INF
│ │ └── jsp
│ ├── manager
│ │ ├── css
│ │ ├── images
│ │ ├── META-INF
│ │ └── WEB-INF
│ │ └── jsp
│ └── ROOT
│ └── WEB-INF
└── work # jsp编译之后的结构文件,需要提前预热访问,升级应用之后,删除此目录才能更新
配置文件
文件名 | 说明 |
---|---|
server.xml | 主配置文件 |
web.xml | 定义和部署webapp |
context.xml | 定义所有web程序均需加载的Context配置 |
tomcat-user.xml | 用户认证的账号和密码文件 |
catalina.policy | 当使用security选项启动tomcat时,用于为tomcat设置安全策略 |
catalina.properties | tomcat环境变量的配置,用于设定类加器路径,以及JVM调优相关参数 |
logging.properties | tomcat日志相关配置,可以修该日志级别和日志路径 |
核心组件
名称 | 说明 |
---|---|
Server | 服务器,tomcat运行的实例 |
Service | 服务,用来组织Engin和Connector的对应关系,一个service中只有一个engine |
Connector | 连接器,负责客户端的http、https、ajp等协议连接,一个connector只属于某一个engine |
Engine | 引擎,用来响应并处理用户的请求 |
Host | 虚拟主机,可实现多虚拟主机 |
Context | 应用的上下文,配置特定url路径映射和目录映射关系 |
[root@tomcat]grep -v '\-\-' ./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"
maxParameterCount="1000"
/>
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxParameterCount="1000"
/>
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true"
maxParameterCount="1000"
>
</Connector>
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443"
maxParameterCount="1000"
/>
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>
</Engine>
</Service>
</Server>
处理请求
如果用户访问http://localhost:8080/test/index.jsp
- 浏览器请求被发送到服务器端口8080,tomcat监听此端口,通过侦听http/1.1/Connector获取请求
- Connector将请求交给所在Server的Engine来处理,并等待engine的响应
- engine获得请求,遍历它所有虚拟主机hosts
- 匹配到localhosts主机,否则交由defaulthost处理
- host匹配到路径请求为/test/index.jsp,匹配它所拥有的Context
- 请求匹配到path=/test的contest获得请求index.jsp,在它的mapping table中寻找对应的servlet
- context匹配到url 参数为*.jsp的servlet,对应于jspservlet类狗仔httpServletRequest对象和HttpServletResponse对象,作为参数调用jspServlet的doGet或者doPost方法
- Context把HttpServletResponse对象返回给hosts
- host把HttpServletResponse对象返回给engine
- engine把HttpServletResponse对象返回给Connector
- Connector把HttpServletResponse对象返回给浏览器端
部署站点
配置文件
Tomcat中默认网站根目录是$CATALINA_BASE/webapps/,其下的ROOT目录就是网站默认根目录,webapps下的每一个目录对应一个web应用,即WebAPP。每一个虚拟主机都可以使用appBase指令配置自己的站点目录,使用appBase目录下的ROOT目录为主站目录。webapps目录可能有子目录,但非必须:
- 主页配置:默认按照 index.html index.htm index.jsp 顺序查找
- WEB-INF: 当前目录webapp的私有资源路径,通常存粹web.xml和context.xml
- META-INF: 类似WEB-INF,私有资源配置信息,浏览器无法访问
- classes/: 类文件
- lib/: 当前应用依赖的jar包
部署方式
- WebApp应用的归档格式
- .war: 类zip格式文件,包括一个应用的所有资源,例如jsp、html、配置文件等
- .jar: EJB类文件打包压缩类zip格式文件,包括很多class文件
- .rar: 资源适配器文件,目前已不常用
- .ear: 企业级webapp打包,目前已不常用
- 部署方式:
- 部署Deploy:将webapp源文件放到目标目录,通过web.xml和context.xml文件配置路径访问应用程序
- 自动部署
- 手动部署:
- 冷部署
- 热部署
- 反部署undeploy
- 启动
- 停止
- 部署Deploy:将webapp源文件放到目标目录,通过web.xml和context.xml文件配置路径访问应用程序
构建WAR包部署
# 创建目录
[root@tomcat ~]# pwd
/root
[root@tomcat ~]# mkdir app
[root@tomcat ~]# cd app
[root@tomcat app]# touch test.html
[root@tomcat app]# touch test.jsp
[root@tomcat app]# cat test.html
<h1>This is Test HTML. </h1>
[root@tomcat app]# cat 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>
# 生成war包
[root@tomcat app]# jar cvf app.war *
added manifest
adding: test.html(in = 29) (out= 28)(deflated 3%)
adding: test.jsp(in = 365) (out= 301)(deflated 17%)
[root@tomcat app]# file app.war
app.war: Java archive data (JAR)
# 部署war包
[root@tomcat app]# chown tomcat:tomcat app.war
[root@tomcat app]# cp -p app.war /usr/libexec/tomcat/webapps/
# 自动解压缩
[root@tomcat app]# ll /usr/libexec/tomcat/webapps/
total 12
drwxr-x--- 3 tomcat tomcat 55 Sep 14 12:49 app
-rw-r--r-- 1 tomcat tomcat 886 Sep 14 12:44 app.war
drwxr-x--- 3 tomcat tomcat 4096 Sep 14 12:01 ROOT
[root@tomcat app]# lynx 127.0.0.1:8080/app/test.jsp
后面的内容是服务器端动态生成字符串,最后拼接在一起 hello jsp
http://127.0.0.1:8080/app/test.jsp
[root@tomcat app]# lynx 127.0.0.1:8080/app/test.html
<This is Test HTML.
# 访问之后自动生成.class和.java文件
[root@tomcat app]# tree /usr/libexec/tomcat/work/Catalina/localhost/app/
/usr/libexec/tomcat/work/Catalina/localhost/app/
└── org
└── apache
└── jsp
├── test_jsp.class
└── test_jsp.java
3 directories, 2 files
# 自动卸载
[root@tomcat app]# rm /usr/libexec/tomcat/webapps/app.war
rm: remove regular file '/usr/libexec/tomcat/webapps/app.war'? y
# 之后webapps和work目录下对应app目录自动删除。
管理页面
Tomcat自带管理app,但默认是不许访问,需要配置开启
# 修改conf/tomcat-user.xml文件
[root@tomcat ~]# vim /usr/libexec/tomcat/conf/tomcat-user.xml
# 在<tomcat-user>之后添加
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="admin" password="123456" roles="manager-gui,admin-gui"/>
[root@tomcat ~]# vim /usr/libexec/tomcat/webapps/manager/META-INF/context.xml
# 允许localhost之外的地址访问
allow="127.0.0.1|192.168.10.* />
# 重启服务
[root@tomcat ~]# systemctl restart tomcat
后台管理页面
服务状态页面
其他配置
多主机设置
配置说明
- name必须是主机名,用主机名来匹配
- appBase当前主机的站点根目录
- unpackWARs 是否自动解压war格式
- autoDeploy 热部署,自动加载并运行应用
配置过程
# 添加多站点配置文件
[root@tomcat ~]# vim /usr/libexec/tomcat/conf/server.xml
# 在localhost之后添加
<Host name="1.sujx.net" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="sujx.net_1_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="2.sujx.net" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="sujx.net_2_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
# 创建目录
[root@tomcat ~]# mkdir -p /data/web{1,2}/ROOT/
# 将前述test.jsp文件复制为index.jsp
[root@tomcat ~]# cp index.jsp /data/web{1,2}/ROOT/
8005端口配置
8005端口是tomcat的管理端口,默认监听在127.0.0.1上,无需验证即可发送SHUTDOWN整个字符串来关闭tomcat。
[root@tomcat ~]# vim /usr/libexec/tomcat/conf/server.xml
<Server port="8005" shutdown="SHUTDOWN">
该配置项无法注释,否则无法启动tomcat。解决措施有:
- 修改SHUTDOWN字符串为随机字符;
- 修改端口号为0,会使用随机端口;
- 修改端口号为-1,将关闭该功能。
修改服务器版本信息
默认不显示tomcat的HTTP的Server头信息,可以修改为其他值
[root@tomcat ~]# vim /usr/libexec/tomcat/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxParameterCount="1000"
server="sujx home lab" # 新增配置项
/>
[root@tomcat ~]# http 127.0.0.1:8080
HTTP/1.1 200
Connection: keep-alive
Content-Type: text/html;charset=UTF-8
Date: Thu, 14 Sep 2023 07:53:47 GMT
Keep-Alive: timeout=20
Server: sujx home lab
Transfer-Encoding: chunked
修改访问端口为80
Tomcat用户运行时不能直接使用1024以下端口,需要修改tomcat的运行身份
# 将8080修改为80端口
[root@tomcat ~]# vim /usr/libexec/tomcat/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxParameterCount="1000"
/>
# 修改程序运行用户
[root@tomcat ~]# vim /lib/systemd/system/tomcat.service
[Unit]
Description=Apache Tomcat 10
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/libexec/tomcat/bin/startup.sh
ExecStop=/usr/libexec/tomcat/bin/shutdown.sh
RemainAfterExit=yes
# User=tomcat
# Group=tomcat
[Install]
WantedBy=multi-user.target
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.