Appearance
J2EE 应用 Linux 部署标准流程
本文适用于基于 Servlet/JSP 的传统 J2EE Web 应用(如使用 Apache Tomcat 作为容器),目标是构建可复现、可维护、符合最小权限原则的生产级部署方案。不适用于 Spring Boot 内嵌容器模式(其部署范式不同,详见《Spring Boot 应用 Linux 部署指南》)。
🎯 目标
- 将编译打包完成的
.war文件安全、可靠地部署至 Linux 服务器; - 启动受 systemd 管理的 Tomcat 服务,支持开机自启与日志归集;
- 避免常见权限、编码、路径配置错误导致的启动失败或运行时异常;
- 满足基础安全要求:非 root 运行、独立用户隔离、静态资源权限收敛。
⚙️ 前置条件
系统环境
- 操作系统:CentOS 7+/Rocky Linux 8+ 或 Ubuntu 20.04+(推荐 LTS 版本);
- 内存:≥2 GB(建议 4 GB+,视应用规模调整);
- Java 运行时:OpenJDK 11 或 17(必须与应用编译版本兼容);bash
java -version # 输出应类似:openjdk version "17.0.1"...
必备组件
- Apache Tomcat 9.x 或 10.x(注意:Tomcat 10+ 默认启用 Jakarta EE 9+ 命名空间,需确认应用已迁移
jakarta.*包); systemd(现代 Linux 发行版默认启用);unzip、curl、rsync(用于传输与解压)。
权限与用户约定
- 禁止以 root 用户直接运行 Tomcat;
- 创建专用低权限用户(如
tomcat),归属独立用户组(如tomcat); - 所有 Tomcat 目录(
CATALINA_HOME、CATALINA_BASE)归属该用户,权限设为750; - WAR 包上传目录(如
/opt/deploy/)对部署用户可写,对tomcat用户只读。
🛠️ 标准部署步骤
1. 创建部署用户与目录结构
bash
# 创建用户(无登录 shell,主目录禁用)
sudo useradd -r -s /bin/false -d /opt/tomcat tomcat
# 创建标准目录结构
sudo mkdir -p /opt/tomcat/{bin,conf,logs,webapps,work,temp}
sudo chown -R tomcat:tomcat /opt/tomcat
sudo chmod -R 750 /opt/tomcat
# 创建部署中转目录(供 CI/CD 或人工上传)
sudo mkdir -p /opt/deploy
sudo chown deployer:deployer /opt/deploy # 假设由 deployer 用户上传
sudo chmod 755 /opt/deploy2. 配置 Tomcat 运行环境
编辑 /opt/tomcat/bin/setenv.sh(若不存在则新建),设置关键 JVM 参数与编码:
bash
#!/bin/bash
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 # 根据实际路径调整
export CATALINA_HOME=/opt/tomcat
export CATALINA_BASE=/opt/tomcat
export CATALINA_PID=/opt/tomcat/tomcat.pid
export CATALINA_OUT=/opt/tomcat/logs/catalina.out
# 关键:强制 UTF-8 编码(避免中文乱码、表单提交异常)
export JAVA_OPTS="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
# 生产建议:堆内存与 GC 策略
export JAVA_OPTS="$JAVA_OPTS -Xms512m -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200"✅ 注意:
setenv.sh需添加执行权限:sudo chmod +x /opt/tomcat/bin/setenv.sh
3. 部署 WAR 包
bash
# 假设 WAR 包已上传至 /opt/deploy/myapp.war
sudo cp /opt/deploy/myapp.war /opt/tomcat/webapps/
# Tomcat 会自动解压(确保 webapps 目录下无同名目录残留)
# 如需跳过自动解压,可重命名为 myapp.war?unpack=false(Tomcat 9+)
# 推荐方式:先清空再部署(避免旧 class/配置残留)
sudo systemctl stop tomcat
sudo rm -rf /opt/tomcat/webapps/myapp* # 清理历史版本
sudo cp /opt/deploy/myapp.war /opt/tomcat/webapps/
sudo chown tomcat:tomcat /opt/tomcat/webapps/myapp.war4. 编写 systemd 服务单元文件
创建 /etc/systemd/system/tomcat.service:
ini
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
Environment=CATALINA_PID=/opt/tomcat/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
Environment='CATALINA_OPTS=-Xms512M -Xmx2G -server -XX:+UseG1GC'
Environment='JAVA_OPTS=-Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom'
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
RestartSec=10
Restart=always
[Install]
WantedBy=multi-user.target启用并启动服务:
bash
sudo systemctl daemon-reload
sudo systemctl enable tomcat
sudo systemctl start tomcat
sudo systemctl status tomcat # 验证运行状态5. 验证与基础访问控制
- 检查端口监听:
sudo ss -tuln | grep :8080; - 访问
http://<server-ip>:8080/myapp/(确保应用上下文路径正确); - 查看日志定位问题:
sudo journalctl -u tomcat -f或tail -f /opt/tomcat/logs/catalina.out; - 关闭 Tomcat Manager 默认页面(生产必需):
- 删除
/opt/tomcat/webapps/manager和/opt/tomcat/webapps/host-manager; - 或注释
/opt/tomcat/conf/tomcat-users.xml中相关<role>与<user>配置。
- 删除
⚠️ 关键注意事项
- WAR 包命名即上下文路径:
myapp.war→ 访问路径为/myapp/;ROOT.war→ 访问根路径/; - 时区一致性:确保服务器
TZ与应用JVM时区一致(推荐export JAVA_OPTS="$JAVA_OPTS -Duser.timezone=Asia/Shanghai"); - 静态资源缓存:如使用 Nginx 做反向代理,务必配置
Cache-Control头,避免浏览器加载过期 JS/CSS; - JDBC 连接池配置:生产环境应将数据库连接信息移出
WEB-INF/web.xml,改用 JNDI 或外部配置(如context.xml),避免敏感信息硬编码; - SELinux / AppArmor:如启用,需额外放行 Tomcat 网络端口与文件访问策略(CentOS/RHEL 默认启用 SELinux)。
❓ 常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
Failed to start tomcat.service: Unit tomcat.service not found | systemd 单元文件路径错误或未重载 | 检查文件路径是否为 /etc/systemd/system/tomcat.service;执行 sudo systemctl daemon-reload |
启动后 8080 端口无响应,日志无报错 | Tomcat 进程崩溃退出(PID 文件残留) | 清理 /opt/tomcat/tomcat.pid,重启服务;检查 JAVA_HOME 路径是否真实存在 |
| 中文参数乱码(如表单提交) | 请求编码未统一 | 在 conf/server.xml 的 Connector 中添加 URIEncoding="UTF-8":<Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8" ... /> |
java.lang.OutOfMemoryError: Metaspace | Metaspace 不足(尤其热部署频繁时) | 在 setenv.sh 中添加:export JAVA_OPTS="$JAVA_OPTS -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m" |
| WAR 包未自动解压 | autoDeploy="false" 或 deployOnStartup="false" | 检查 conf/server.xml 中 <Host> 标签属性,确保为默认值 true |
