Tomcat使用入门 | Word Count: 3.2k | Reading Time: 15mins | Post Views:
Tomcat是一个免费的开放源代码的Web应用服务器,具有处理HTML静态资源页面的功能,同时它还是一个Servlet和JSP的容器。Tomcat于1999年发布,初始版本为3.0,实现了Servlet2.2和JSP1.1的规范。
Tomcat的核心分为3个部分:
Web容器:负责处理静态页面;
JSP容器:把JSP页面翻译为一般的Servlet
Catalina:是一个servlet容器,用于处理servlet
部署服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 # 安装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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 # 测试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
配置管理 目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 [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路径映射和目录映射关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 [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
启动
停止
构建WAR包部署 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 # 创建目录 [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,但默认是不许访问,需要配置开启
1 2 3 4 5 6 7 8 9 10 11 # 修改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 热部署,自动加载并运行应用
配置过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 添加多站点配置文件 [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。
1 2 [root@tomcat ~]# vim /usr/libexec/tomcat/conf/server.xml <Server port="8005" shutdown="SHUTDOWN">
该配置项无法注释,否则无法启动tomcat。解决措施有:
修改SHUTDOWN字符串为随机字符;
修改端口号为0,会使用随机端口;
修改端口号为-1,将关闭该功能。
修改服务器版本信息 默认不显示tomcat的HTTP的Server头信息,可以修改为其他值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [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的运行身份
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # 将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