tomcat应用服务
tomcat
目前互联网WEB应用服务器:
- 商用: IBM WebSphere、Oracle WebLogic(原属于BEA公司)、Oracle Oc4j、JBoss(红帽开发)等
- 开源: Tomcat、Jetty、Resin、Glassfish
Tomcat 介绍:
免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,Tomcat具有处理HTML页面的功能,它还是一个Servlet和JSP容器
Tomcat 仅仅实现了Java EE规范中与Servlet、JSP相关的类库,是JavaEE不完整实现
官网: http://tomcat.apache.org/
官网文档: https://tomcat.apache.org/tomcat-8.5-doc/index.html
帮助文档:
- https://cwiki.apache.org/confluence/display/tomcat/
- https://cwiki.apache.org/confluence/display/tomcat/FAQ
Tomcat的核心分为3个部分:
- Web容器:处理静态页面
- JSP容器:把jsp页面翻译成一般的 servlet
- catalina(美国地名): 是一个servlet容器,用于处理servlet
目录文件说明:
- bin 服务启动、停止等相关程序和文件
- conf 配置文件
- lib 库目录
- webapps 应用程序部署目录,相当于/var/www/html/的作用,但是tomcat自己的默认网页index.jsp文件在子目录:ROOT/index.jsp
- work jsp编译后的结果文件存放目录,建议java程序部署后提前预热访问
- logs 日志存放
- temp 临时文件目录,如缓存存放
配置文件:
官方文档:http://tomcat.apache.org/tomcat-8.5-doc/index.html
| server.xml | 主配置文件,最重要的文件 |
| web.xml | 每个webapp只有“部署”后才能被访问,它的部署方式通常由web.xml进行定义,其存放位置为WEB-INF/目录中。此文件为所有的webapps提供默认部署相关的配置,每个web应用也可以使用专用的web/xml配置文件,来覆盖全局文件 |
| context.xml | 用于定义所有web应用均需加载的Context配置,此文件为所有的webapps提供默认配置,每个web应用也可以使用自已专用的配置,它通常由专用的配置文件context.xml来定义,其存放位置为WEB-INF/目录中,覆盖全局的文件 |
| tomcat-users.xml | 用户认证的账号和密码文件 |
| catalina.policy | 当使用security选项启动tomcat时,用于为tomcat设置安全策略 |
| catalina.properties | Tomcat环境变量的配置,用于设定类加载器路径,以及一些与JVM调优相关参数 |
| logging.properties | Tomcat日志系统相关的配置,可以修改日志级别和日志路径等 |
server.xml配置说明:
service配置:
一般情况下,一个Server实例配置一个Service,name属性相当于该Service的ID
<Service name="Catalina">
连接器配置说明:
redirectPort,如果访问HTTPS协议,自动转向这个连接器。但大多数时候,Tomcat并不会开启HTTPS,因为Tomcat往往部署在内部,HTTPS性能较差
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
引擎配置:
defaultHost指向内部定义某虚拟主机。缺省虚拟主机可以改动,默认localhost
<Engine name="Catalina" defaultHost="localhost">
虚拟主机配置:
- name 必须是主机名,用主机名来匹配
- appBase是当前主机的网页根目录,是相对于$CATALINA_HOME ,也可以使用绝对路径
- unpackWARs 是否自动解压war格式
- autoDeploy 热部署,自动加载并运行应用
配置:
方法1:
vim conf/server.xml
#在文件最后面增加下面内容
<Host name="www.hj.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>
方法2:
vim conf/server.xml
<Host name="web1.hj.com" appBase="/data/webapps1/" unpackWARs="True" autoDeploy="false"></Host>
<Host name="web2.hj.com" appBase="/data/webapps2/" unpackWARs="True" autoDeploy="false"></Host>
最后测试访问:
mkdir /data/webapps{1,2}/ROOT
echo web1 > /data/webapps1/ROOT/index.html
echo web2 > /data/webapps2/ROOT/index.html
echo '2.2.2.12 web1.hj.com web2.hj.com' > /etc/hosts
context配置:
作用:
- 路径映射:将url映射至指定路径,而非使用appBase下的物理目录,实现虚拟目录功能
- 应用独立配置,例如单独配置应用日志、单独配置应用访问控制
#在虚拟主机内配置
vim conf/server.xml
<Host ...>
<Context path="/test" docBase="/data/test" reloadable="true" />
</Host>
说明:
- path:指的是访问的URL路径,如果path与appBase下面的子目录同名,context的docBase路径优先更高
- docBase:可以是磁盘文件的绝对路径,也可以是相对路径(相对于Host的appBase)
- reloadable:true表示如果WEB-INF/classes或META-INF/lib目录下.class文件有改动,就会将
- WEB应用重新加载。生产环境中,建议使用false来禁用
例:
这里特别使用了软链接,原因方便后期版升级或回滚,如是是版本升级,需要将软链接指向myappv2,重新启动。如果新版上线后,出现问题,重新修改软链接到上一个版本的目录,并重启,就可以实现回滚
mkdir /opt/newweb
ln -sv /opt/newweb /opt/web
echo new web page > /opt/newweb/index.html
vim /conf/server.xml
<Context path="/test" docBase="/opt/web" reloadable="true" />
valve组件:
valve(阀门)组件可以定义日志
两种类型:
- 定义访问日志:org.apache.catalina.valves.AccessLogValve
- 定义访问控制:org.apache.catalina.valves.RemoteAddrValve
例: 关闭日志,并拒绝记录来自某ip
<Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="2\.0\.0\.\d+"/>
例2: 设置日志
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
日志文件:
参考文档:https://cwiki.apache.org/confluence/display/TOMCAT/Logging
日志格式文档:https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Access_Logging
本地日志格式文档:http://2.2.2.12:8080/docs/config/valve.html#Access_Logging
日志类型:
- catalina.时间.log tomcat服务日志
- catalina.out tomcat服务日志
- host-manager.时间.log host manager管理日志
- locahost.时间.log 默认主机日志
- localhost_access_log.时间.log 默认主机访问日志
- manager.时间.log 管理日志
日志定义:
日志在server.xml中的最后几行定义:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
日志定义参数:
%a :远程IP地址
%A :本地IP地址
%b :发送的字节数,不包括HTTP头,或“ :”如果没有发送字节
%B :发送的字节数,不包括HTTP头
%D :处理请求的时间(以毫秒为单位)
%h :远程主机名
%H :请求协议
%I (大写的i) :当前请求的线程名称
%l (小写的L):远程逻辑从identd的用户名(总是返回' :')
%m :请求方法
%p :本地端口
%q :查询字符串(在前面加上一个“?”如果它存在,否则是一个空字符串
%r :请求报文第一行
%s :响应的HTTP状态代码
%S :用户会话ID
%t :日期和时间,在通用日志格式
%T :处理请求的时间(以秒为单位)
%u :远程用户身份验证
%U :请求的URL路径
%v :本地服务器名
X
+
-
"" html语言中表示双引号""
%{xxx}i
%{xxx}o
%{xxx}c
%{xxx}r
%{xxx}s
%{xxx}p
%{xxx}t
tomcat程序组件:
组件分层和分类:
- 顶级组件: server,为一个tomcat服务(容器),一台主机可启动多个tomcat实例,但要避免端口冲突
- 服务类组件: service,实现engine、connector,建立两者之间的关系,一个service只能有一个engine
- 连接器组件: connector,有http(默认端口8080/tcp)、https(默认端口8443/tcp)、ajp(默认端口8009/tcp)协议的连接器,AJP(apache jserv protocol)是一种基于tcp的二进制通讯协议
- 容器类: engine、host(虚拟主机)、context(上下文件,解决路径映射)都是容器类组件,可以嵌入其他组件
- 内嵌类: 可以内嵌到其他组件内,valve、logger、realm、loader、manager等。如:logger,可以在容器组件内分别定义
- 集群类组件: listener、cluster
tomcat内部组成:
- server:
- service: 用来组织Engine和Connector的对应关系
- connector: 连接器,负责客户端的HTTP、HTTPS、AJP等协议连接。一个Connector只属于某一个Engine
- engine: 即引擎,用来响应并处理用户请求。一个Engine上可以绑定多个Connector
- host: 即虚拟主机,可以实现多虚拟主机,例如使用不同的主机头区分
- context: 应用的上下文,配置特定url路径映射和目录的映射关系:url => directory
例:主配置文件中的组件定义关系
<?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">
<Context >
<Context />
</Host>
</Engine>
</Service>
</Server>
tomcat处理请求过程:
如果请求url为:http://localhost:8080/test/index.jsp
- 浏览器端的请求被发送到服务端端口8080,Tomcat进程监听在此端口上。通过侦听的HTTP/1.1 Connector获得此请求
- Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的响应
- Engine获得请求localhost:8080/test/index.jsp,遍历它所有虚拟主机Host
- Engine匹配到名为localhost的Host。如果匹配不到,就把请求交给该Engine中的defaultHost处理
- localhost Host获得请求/test/index.jsp,匹配它所拥有的所有Context
- Host匹配到路径为/test的Context
- path=/test的Context获得请求index.jsp,在它的mapping table中寻找对应的servlet
- Context匹配到URL PATTERN为*.jsp 的servlet,对应于JspServlet类构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法。
- Context把执行完了之后的HttpServletResponse对象返回给Host
- Host把HttpServletResponse对象返回给Engine
- Engine把HttpServletResponse对象返回给Connector
- Connector把HttpServletResponse对象返回给浏览器端
应用部署:
tomcat的根目录结构:
默认网站根目录是$CATALINA_BASE/webapps/,下面的每一个子目录对应一个请求资源目录
但tomcat有一个特殊的地方在于,实际默认网站的根目录在$CATALINA_BASE/webapps/ROOT/下面
catalina.sh version #查看变量,CATALINA_BASE为安装目录
例:
#创建一个单独的url路径,测试访问,http://tomcat:8080/test 对应 webapps/test/index.html
mkdir webapps/test
echo test web > webapps/test/index.html
curl 127.0.0.1:8080/test/index.html
#在根url下创建一个资源文件,测试访问,http://tomcat:8080/index.html 对应>webapps/ROOT/index.html
echo webapps html > webapps/ROOT/index.html
curl 127.0.0.1:8080/index.html
访问页面时编码问题:
默认nginx、tomcat没有在响应报文中返回字符集,所以页面中的中文不能正常显示,一般要在服务中设置默认字符集或html代码中指定
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>tomcat</title>
</head>
<h1>一二三四</h1>
JSP WebApp目录结构:
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包
主页设置:
配置规则:
- webApp的专有配置优先于系统的全局配置
- 修改系统的全局配置文件,需要重新启动服务生效
- 修改webApp的专有配置,无需重启即可生效
全局配置实现修改默认主页文件:
默认情况下tomcat会在webapps/ROOT/目录下按以下次序查找文件,找到第一个则进行显示
可以通过修改conf/web.xml中的下面<welcome-file-list>标签 内容修改默认页文件
- index.html
- index.htm
- index.jsp
WebApp的专用配置文件:
webapps/应用目录/WEB-INF/web.xml
配置规则:
- webApp的专有配置优先于系统的全局配置
- 修改系统的全局配置文件,需要重新启动服务生效
- 修改 webApp的专有配置,无需重启即可生效
例:
echo web html > webapps/test/index.html
echo web htm > webapps/test/index.htm
curl 127.0.0.1:8080/test/ #此时还是返回html的
cp -r ROOT/WEB-INF test/
vim test/WEB-INF/web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
应用部署实现:
WebApp应用的归档格式:
传统应用开发测试后,通常打包为war格式,这种文件部署到Tomcat的webapps目录下,并默认会自动解包展开和部署上线
| .war | WebApp打包,类zip格式文件,通常包括一个应用的所有资源,比如jsp,html,配置文件等 |
| .jar | EJB类文件的打包压缩类zip格式文件,,包括很多的class文件 |
| .rar | 资源适配器类打包文件,目前已不常用 |
| .ear | 企业级WebApp打包,目前已不常用 |
Deploy部署方式:
将webapp的源文件放置到目标目录,通过web.xml和context.xml文件中配置的路径就可以访问该webapp,通过类加载器加载其特有的类和依赖的类到JVM上,即:最终用户可以通过浏览器访问该应用
- 自动部署: Tomcat一旦发现多了一个web应用APP.war包,默认会自动把它解压缩,加载并启动起来
在server.xml默认配置为:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
虚拟主机是localhost,家目录是webapps,自动解压war包,自动部署
- 手动部署
- 冷部署:将webapp放到指定目录,才去启动Tomcat服务
- 热部署:Tomcat服务不停止,需要依赖manager、ant脚本、tcd(tomcat client deployer)等工具
- 反部署undeploy(删除): 停止webapp运行,并从JVM上清除已经加载的类,从Tomcat应用目录中移除部署的文件
- 启动start: 是webapp能够访问
- 停止stop: webapp不能访问,不能提供服务,但是JVM并不清除它
手动部署:
mkdir webapps/app1/ ;cd webapps/app1/
vim test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<% out.println("test jsp"); %>
<br>
<%=request.getRequestURL()%>
</body>
</html>
#测试访问
curl http://127.0.0.1:8080/app1/test.jsp
自动部署:
部署基于java的博客JPress
源码下载:http://www.jpress.io/download
1)自动部署
cp jpress-v4.0.6.war /tomcat/webapps/
cd /tomcat/webapps/
ln -sv jpress-v4.0.6 jpress
2)安装数据库
yum -y install mysql-server
systemctl enable --now mysqld
mysql -e 'create database jpress'
mysql -e 'grant all on jpress.* to jpress@"2.%" identified by "123456"'
3)web界面操作
上传时的图片存放路径:jpress/attachment/
常见配置:
web界面管理服务status和app:
tomcat提供了基于WEB的管理页面,默认由tomcat-admin-webapps.noarch包提供相关文件
默认访问管理页面,会出现403错误,因为管理页面默认是禁止的,所以需要打开用户认证,设置管理用户
启用方法:
#添加允许查看的账户和密码
vim conf/tomcat-users.xml
<role rolename="manager-gui"/>
<user username="tomcat" password="123456" roles="manager-gui"/>
#添加允许访问的ip,基于正则表达式匹配,"|"为或,\d为数字,+为多个
vim webapps/manager/META-INF/context.xml
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|2\.\d+\.\d+\.\d+" />
基于web方式的Host Manager虚拟主机管理:
默认Host Manager 管理页被禁用
启用:
vim tomcat-users.xml
<role rolename="manager-gui"/>
<role rolename="admin-gui" />
<user username="admin" password="123456" roles="manager-gui,admin-gui"/>
vim webapps/host-manager/META-INF/context.xml
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|2\.\d+\.\d+\.\d+" />
端口8005/tcp安全配置管理:
此端口是用来关闭tomcat服务的端口,可不用输密码,直接telnet连接发送关闭服务命令,所以很危险
此管理功能建议禁用,可将SHUTDOWN改为一串猜不出的字符串实现,或者port修改成0, 或使用随机端口,如:36913
port设为-1等无效端口,将关闭此功能
此行不能被注释,否则无法启动tomcat服务
修改端口:
openssl rand -base64 8 #此处随机字符做密码
vim server.xml
<Server port="8005" shutdown="随机字符">
systemctl restart tomcat
telnet 127.0.0.1 8005 #此时连接后必须输刚刚的随机字符才能关闭服务
显示指定的http服务器版本信息:
默认不会在http的响应头显示tomcat的server信息, 可以指定tomcat的http的Server头信息为相应的值
修改:
vim server.xml
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" Server="hj-linux" />

浙公网安备 33010602011771号