现代Java Web应用部署全栈实战:Tomcat集群+JDK17+Spring Boot+Nginx负载均衡
一、前言:为什么我们需要 Tomcat 集群?
在当今的 Web 开发中,单机部署已难以满足高并发、高可用和高性能的需求。Tomcat 作为最主流的 Java Web 容器,虽然轻量高效,但面对流量洪峰时仍显单薄。
因此,构建一个基于 Nginx + Tomcat 集群 的架构,不仅能实现负载均衡与故障转移,还能通过动静分离提升整体性能。
二、Java 运行基石:JVM、JRE 与 JDK
在部署 Tomcat 之前,必须理解 Java 的运行机制。
| 概念 | 说明 |
|---|---|
| JVM | Java 虚拟机,负责将 .class 字节码解释为机器码执行,是跨平台的核心。 |
| JRE | Java 运行时环境,包含 JVM + 核心类库,适合仅运行 Java 程序。 |
| JDK | Java 开发工具包,包含 JRE + 编译器(javac)、调试器等开发工具。 |
✅ 结论:无论是开发还是部署,都应安装 JDK。
推荐选择:OpenJDK 17(LTS)
- LTS(Long-Term Support):长期支持版本,稳定性强,社区活跃。
- 主流发行版:Amazon Corretto、Azul Zulu、Eclipse Temurin、Oracle OpenJDK。
- 本文选用 Amazon Corretto 17,免费且生产就绪。
三、环境准备
| 主机名 | 内网 IP | 角色说明 |
|---|---|---|
| web03 | 172.16.1.9 | 主节点:Tomcat + Nginx + 后端 |
| web04 | 172.16.1.10 | 备用节点:Tomcat 集群扩展 |
| db01 | 172.16.1.51 | MySQL 数据库服务 |
所有操作均以
root用户执行,生产环境建议降权运行。
四、部署 JDK 17(二进制方式)
#!/bin/bash
# JDK 17 安装脚本# 1. 创建工具目录
mkdir -p /app/tools/# 2. 下载 OpenJDK 17 (Amazon Corretto)
echo "正在下载 JDK 17..."
wget -O /app/tools/jdk-17.tar.gz \https://corretto.aws/downloads/latest/amazon-corretto-17-x64-linux-jdk.tar.gz# 3. 解压
echo "正在解压 JDK..."
tar xf /app/tools/jdk-17.tar.gz -C /app/tools/# 4. 创建软链接便于管理
JDK_DIR=$(tar tf /app/tools/jdk-17.tar.gz | head -1 | cut -f1 -d"/")
ln -sf /app/tools/$JDK_DIR /app/tools/jdk# 5. 配置全局环境变量
echo "配置环境变量..."
cat >> /etc/profile <<'EOF'# Java Environment
export JAVA_HOME=/app/tools/jdk
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
EOF# 6. 加载环境变量
source /etc/profile# 7. 验证安装
echo "验证 Java 安装..."
java -versionif [ $? -eq 0 ]; thenecho "✅ JDK 17 安装成功!"
elseecho "❌ JDK 17 安装失败!"exit 1
fi
输出示例:
openjdk version "17.0.17" 2025-10-21 LTS
OpenJDK Runtime Environment Corretto-17.0.17.10.1 (build 17.0.17+10-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.17.10.1 (build 17.0.17+10-LTS, mixed mode, sharing)
五、部署 Apache Tomcat 9(兼容 JDK 17)
Tomcat 9.0.x 支持 JDK 8 ~ JDK 17,是当前稳定选择。
#!/bin/bash
# Tomcat 9 安装脚本# 1. 下载 Tomcat 9.0.111
echo "正在下载 Tomcat 9..."
wget -O /app/tools/apache-tomcat-9.0.111.tar.gz \https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.111/bin/apache-tomcat-9.0.111.tar.gz# 2. 解压并创建软链接
echo "正在解压 Tomcat..."
tar xf /app/tools/apache-tomcat-9.0.111.tar.gz -C /app/tools/
ln -sf /app/tools/apache-tomcat-9.0.111 /app/tools/tomcat# 3. 验证版本信息
echo "验证 Tomcat 版本..."
/app/tools/tomcat/bin/version.sh# 4. 设置执行权限
chmod +x /app/tools/tomcat/bin/*.shecho "✅ Tomcat 9 安装完成!"
六、Tomcat 目录结构详解
| 目录 | 用途说明 |
|---|---|
bin/ | 启动/关闭脚本(startup.sh, shutdown.sh) |
conf/ | 核心配置文件(server.xml, web.xml, tomcat-users.xml) |
lib/ | 共享类库(JAR 包) |
logs/ | 日志文件(访问日志、错误日志) |
webapps/ | Web 应用部署目录(自动解压 WAR 包) |
work/ | JSP 编译后的 Servlet 文件存放地 |
temp/ | 临时文件目录 |
七、使用 systemctl 管理 Tomcat 服务(推荐)
为了让 Tomcat 支持开机自启和状态管理,需编写 systemd 服务文件。
1. 创建服务单元文件
# 创建 systemd 服务文件
cat > /etc/systemd/system/tomcat.service <<'EOF'
[Unit]
Description=Tomcat 9.0 Java Web Container
After=network.target[Service]
Type=simple
User=root
Group=root
Environment="JAVA_HOME=/app/tools/jdk"
Environment="CATALINA_HOME=/app/tools/tomcat"
Environment="CATALINA_BASE=/app/tools/tomcat"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -Djava.awt.headless=true"
ExecStart=/app/tools/tomcat/bin/catalina.sh run
ExecStop=/app/tools/tomcat/bin/catalina.sh stop
Restart=on-failure
RestartSec=10[Install]
WantedBy=multi-user.target
EOF
2. 启用服务
# 重新加载 systemd 配置
systemctl daemon-reload# 启用并启动 Tomcat 服务
systemctl enable tomcat --now# 检查服务状态
systemctl status tomcat# 查看启动日志
journalctl -u tomcat -f
3. 验证服务
# 检查端口监听
ss -tulnp | grep 8080# 或者使用 netstat
netstat -tulnp | grep 8080# 测试应用访问
curl -v http://localhost:8080
💡 提示:可通过浏览器访问
http://服务器IP:8080验证 Tomcat 是否正常运行。
八、Java 应用部署方式
部署 WAR 包(传统 Web 项目)
适用于基于 Servlet/JSP 的传统 Java Web 应用。需部署到 Tomcat 等容器中运行。
🔧 完整制作与部署流程(无 Maven/IDE)
#!/bin/bash
# WAR 包制作与部署脚本# 1. 创建项目目录
mkdir -p /app/tools/myweb/{WEB-INF/classes,WEB-INF/lib}
cd /app/tools/myweb# 2. 编写 Servlet 源码
cat > HelloServlet.java <<'EOF'
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws IOException {resp.setContentType("text/html;charset=UTF-8");PrintWriter out = resp.getWriter();out.println("<h1>Hello from Java Servlet!</h1>");out.println("<p>服务器时间: " + new java.util.Date() + "</p>");out.println("<p>服务器主机: " + java.net.InetAddress.getLocalHost().getHostName() + "</p>");}
}
EOF# 3. 编译(依赖 Tomcat 的 servlet-api.jar)
echo "编译 Servlet..."
javac -cp "/app/tools/tomcat/lib/servlet-api.jar" \-d WEB-INF/classes \HelloServlet.java# 4. 配置 web.xml(注册 Servlet)
cat > WEB-INF/web.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0"><servlet><servlet-name>HelloServlet</servlet-name><servlet-class>HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.html</welcome-file></welcome-file-list>
</web-app>
EOF# 5. 添加首页(可选)
cat > index.html <<'EOF'
<!DOCTYPE html>
<html>
<head><title>我的 Web 应用</title><meta charset="UTF-8">
</head>
<body><h1>欢迎使用我的 Java Web 应用</h1><p>这是一个手动创建的 WAR 包示例</p><ul><li><a href="hello">调用 Servlet</a></li><li><a href="/">返回 Tomcat 首页</a></li></ul>
</body>
</html>
EOF# 6. 打包为 WAR
echo "打包 WAR 文件..."
jar -cvf ../myweb.war .# 7. 部署到 Tomcat
echo "部署到 Tomcat..."
cp ../myweb.war /app/tools/tomcat/webapps/# 8. 等待部署完成
sleep 5# 9. 验证部署
echo "验证应用部署..."
curl -s http://localhost:8080/myweb/ | head -5echo "应用部署完成!"
echo "访问地址:"
echo " - 首页: http://服务器IP:8080/myweb/"
echo " - Servlet: http://服务器IP:8080/myweb/hello"
💡 说明:
- WAR 文件名决定上下文路径(
myweb.war→/myweb)- 若需根路径访问,重命名为
ROOT.war- 不要将
servlet-api.jar放入WEB-INF/lib/(由 Tomcat 提供)
九、安全建议:禁用管理端或严格限制访问
Tomcat 自带的 manager 和 host-manager 页面存在安全风险,生产环境务必禁用或仅限本地访问。
1. 配置管理用户
# 备份原始配置
cp /app/tools/tomcat/conf/tomcat-users.xml /app/tools/tomcat/conf/tomcat-users.xml.bak# 配置管理用户
cat > /app/tools/tomcat/conf/tomcat-users.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<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"/><role rolename="manager-script"/><role rolename="manager-jmx"/><role rolename="manager-status"/><user username="admin" password="StrongPassword123!" roles="manager-gui,manager-script,manager-jmx,manager-status"/>-->
</tomcat-users>
EOF
2. 限制管理端访问 IP
# 限制 manager 应用访问
cat > /app/tools/tomcat/webapps/manager/META-INF/context.xml <<'EOF'
<Context><Valve className="org.apache.catalina.valves.RemoteAddrValve"allow="127\.0\.0\.1|::1|172\.16\.1\.\d+" />
</Context>
EOF
3. 删除示例应用(推荐生产环境)
# 删除不必要的示例应用
rm -rf /app/tools/tomcat/webapps/docs
rm -rf /app/tools/tomcat/webapps/examples
# rm -rf /app/tools/tomcat/webapps/manager
# rm -rf /app/tools/tomcat/webapps/host-manager# 重启 Tomcat 生效
systemctl restart tomcat
⚠️ 安全警告:生产环境强烈建议删除或严格限制管理端访问。
十、Tomcat 集群:Nginx + Tomcat 实现反向代理
1. 安装 Nginx
# CentOS/RHEL
yum install -y nginx# Ubuntu/Debian
# apt update && apt install -y nginx# 启动 Nginx
systemctl enable nginx --now
2. 配置 Nginx 反向代理
# 创建 Nginx 配置文件
cat > /etc/nginx/conf.d/tomcat-cluster.conf <<'EOF'
upstream tomcat_backend {server 127.0.0.1:8080 weight=3 max_fails=2 fail_timeout=30s;server 172.16.1.10:8080 weight=2 max_fails=2 fail_timeout=30s;# 可选:添加更多 Tomcat 节点# server 172.16.1.11:8080 weight=1;
}server {listen 80;server_name app.freedom.cn;# 隐藏后端信息proxy_hide_header X-Powered-By;proxy_hide_header Server;more_clear_headers 'X-Powered-By' 'Server';# 静态资源缓存location ~* \.(html|css|js|png|jpg|jpeg|gif|ico|svg|woff|ttf)$ {root /app/tools/tomcat/webapps/ROOT;expires 7d;add_header Cache-Control "public, no-transform";access_log off;# 如果静态资源不存在,转发给 Tomcattry_files $uri @tomcat;}# 动态请求转发location @tomcat {proxy_pass http://tomcat_backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;# 超时设置proxy_connect_timeout 30s;proxy_send_timeout 30s;proxy_read_timeout 30s;}# 直接匹配根路径和其他动态请求location / {proxy_pass http://tomcat_backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}# 健康检查location /nginx-status {stub_status on;access_log off;allow 127.0.0.1;allow 172.16.1.0/24;deny all;}
}
EOF# 测试 Nginx 配置
nginx -t# 重新加载 Nginx
systemctl reload nginx
3. 优化 Tomcat 配置
# 修改 server.xml 优化配置
sed -i 's/server="Apache.*"/server="Nginx"/' /app/tools/tomcat/conf/server.xml
sed -i 's/enableLookups="false"/enableLookups="false" compression="on"/' /app/tools/tomcat/conf/server.xml# 重启 Tomcat
systemctl restart tomcat
十一、Tomcat 多实例部署(端口隔离)
在一台服务器上运行多个 Tomcat 实例,避免应用冲突。
#!/bin/bash
# Tomcat 多实例部署脚本# 1. 复制两份实例
echo "创建 Tomcat 多实例..."
cp -r /app/tools/apache-tomcat-9.0.111 /app/tools/tomcat-8081
cp -r /app/tools/apache-tomcat-9.0.111 /app/tools/tomcat-8082# 2. 修改端口(8081 实例)
echo "配置 8081 实例端口..."
sed -i 's/8005/8006/g; s/8080/8081/g; s/8009/8010/g' /app/tools/tomcat-8081/conf/server.xml# 3. 修改端口(8082 实例)
echo "配置 8082 实例端口..."
sed -i 's/8005/8007/g; s/8080/8082/g; s/8009/8011/g' /app/tools/tomcat-8082/conf/server.xml# 4. 创建多实例 systemd 服务文件
cat > /etc/systemd/system/tomcat-8081.service <<'EOF'
[Unit]
Description=Tomcat 9.0 Instance 8081
After=network.target[Service]
Type=simple
User=root
Group=root
Environment="JAVA_HOME=/app/tools/jdk"
Environment="CATALINA_HOME=/app/tools/tomcat-8081"
Environment="CATALINA_BASE=/app/tools/tomcat-8081"
Environment="CATALINA_OPTS=-Xms256M -Xmx512M -server -Djava.awt.headless=true"
ExecStart=/app/tools/tomcat-8081/bin/catalina.sh run
ExecStop=/app/tools/tomcat-8081/bin/catalina.sh stop
Restart=on-failure
RestartSec=10[Install]
WantedBy=multi-user.target
EOFcat > /etc/systemd/system/tomcat-8082.service <<'EOF'
[Unit]
Description=Tomcat 9.0 Instance 8082
After=network.target[Service]
Type=simple
User=root
Group=root
Environment="JAVA_HOME=/app/tools/jdk"
Environment="CATALINA_HOME=/app/tools/tomcat-8082"
Environment="CATALINA_BASE=/app/tools/tomcat-8082"
Environment="CATALINA_OPTS=-Xms256M -Xmx512M -server -Djava.awt.headless=true"
ExecStart=/app/tools/tomcat-8082/bin/catalina.sh run
ExecStop=/app/tools/tomcat-8082/bin/catalina.sh stop
Restart=on-failure
RestartSec=10[Install]
WantedBy=multi-user.target
EOF# 5. 启动多实例服务
systemctl daemon-reload
systemctl enable tomcat-8081 --now
systemctl enable tomcat-8082 --nowecho "✅ Tomcat 多实例部署完成!"
echo "实例1: http://服务器IP:8081"
echo "实例2: http://服务器IP:8082"
十二、现代化部署:Spring Boot 应用
1.安装Maven
# 1. 下载Maven
wget -O /app/tools/apache-maven-3.8.8-bin.tar.gz https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz# 2. 解压
tar xf /app/tools/apache-maven-3.8.8-bin.tar.gz -C /app/tools/# 3. 创建软链接
ln -sf /app/tools/apache-maven-3.8.8 /app/tools/maven# 4. 设置环境变量
cat >> /etc/profile <<'EOF'# Maven Environment
export MAVEN_HOME=/app/tools/maven
export PATH=$MAVEN_HOME/bin:$PATH
EOF# 5. 加载环境变量
source /etc/profile# 6. 验证安装
mvn -version
2.部署:Spring Boot 应用
完整目录结构
simple-springboot-demo/
├── pom.xml
└── src/└── main/├── java/│ └── com/│ └── example/│ └── demo/│ ├── Application.java│ └── controller/│ └── SimpleController.java└── resources/├── application.properties└── static/└── index.html
详细文件内容
1. 项目根目录:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>simple-springboot-demo</artifactId><version>1.0.0</version><packaging>jar</packaging><name>Simple Spring Boot Demo</name><description>A simple Spring Boot web application demo</description><!-- 使用支持 JDK 17 的 Spring Boot 版本 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version> <!-- 这个版本支持 JDK 17 --><relativePath/></parent><properties><java.version>17</java.version> <!-- 改为 17 以匹配你的环境 --><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.example.demo.Application</mainClass></configuration></plugin><!-- 更新编译器配置 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.11.0</version><configuration><source>17</source><target>17</target><encoding>UTF-8</encoding></configuration></plugin></plugins></build>
</project>
2. 主应用类:src/main/java/com/example/demo/Application.java
package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Spring Boot 应用启动类* * @SpringBootApplication 注解表示这是一个Spring Boot应用* 包含:@Configuration, @EnableAutoConfiguration, @ComponentScan*/
@SpringBootApplication
public class Application {/*** 应用主入口方法* * @param args 命令行参数*/public static void main(String[] args) {// 启动Spring Boot应用SpringApplication.run(Application.class, args);System.out.println("=========================================");System.out.println("Spring Boot 应用启动成功!");System.out.println("访问地址: http://localhost:8080");System.out.println("接口测试: http://localhost:8080/hello");System.out.println("健康检查: http://localhost:8080/health");System.out.println("=========================================");}
}
3. 控制器类:src/main/java/com/example/demo/controller/SimpleController.java
package com.example.demo.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;/*** 简单的REST控制器* * @RestController 注解表示这个类是一个REST控制器* 会自动将返回对象转换为JSON格式*/
@RestController
public class SimpleController {/*** 首页欢迎接口*/@GetMapping("/")public Map<String, Object> home() {Map<String, Object> result = new HashMap<>();result.put("message", "欢迎使用 Spring Boot 应用!");result.put("timestamp", LocalDateTime.now().toString());result.put("status", "running");result.put("version", "1.0.0");return result;}/*** 简单的hello接口*/@GetMapping("/hello")public Map<String, Object> sayHello() {Map<String, Object> result = new HashMap<>();result.put("message", "Hello, this is a simple Spring Boot application!");result.put("timestamp", LocalDateTime.now().toString());result.put("server", "Spring Boot 2.7.0");return result;}/*** 带参数的问候接口*/@GetMapping("/greet")public Map<String, Object> greet(@RequestParam(value = "name", defaultValue = "Friend") String name) {Map<String, Object> result = new HashMap<>();result.put("message", "Hello, " + name + "!");result.put("timestamp", LocalDateTime.now().toString());result.put("greeted_user", name);return result;}/*** 健康检查接口*/@GetMapping("/health")public Map<String, Object> healthCheck() {Map<String, Object> result = new HashMap<>();result.put("status", "UP");result.put("timestamp", LocalDateTime.now().toString());result.put("service", "simple-springboot-demo");return result;}/*** 系统信息接口*/@GetMapping("/info")public Map<String, Object> systemInfo() {Runtime runtime = Runtime.getRuntime();Map<String, Object> result = new HashMap<>();result.put("application", "Simple Spring Boot Demo");result.put("version", "1.0.0");result.put("java_version", System.getProperty("java.version"));result.put("os_name", System.getProperty("os.name"));result.put("available_processors", runtime.availableProcessors());result.put("free_memory_mb", runtime.freeMemory() / 1024 / 1024);result.put("total_memory_mb", runtime.totalMemory() / 1024 / 1024);result.put("max_memory_mb", runtime.maxMemory() / 1024 / 1024);result.put("timestamp", LocalDateTime.now().toString());return result;}
}
4. 配置文件:src/main/resources/application.properties
# 应用配置
spring.application.name=simple-springboot-demo# 服务器配置
server.port=8080
server.servlet.context-path=/# 日志配置
logging.level.com.example.demo=INFO
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n# 开发配置(热部署)
spring.devtools.restart.enabled=true# HTTP相关配置
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=true
5. 静态页面:src/main/resources/static/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Spring Boot 演示应用</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);min-height: 100vh;display: flex;align-items: center;justify-content: center;}.container {background: white;padding: 3rem;border-radius: 15px;box-shadow: 0 20px 40px rgba(0,0,0,0.1);text-align: center;max-width: 600px;width: 90%;}h1 {color: #333;margin-bottom: 1rem;font-size: 2.5rem;}.subtitle {color: #666;margin-bottom: 2rem;font-size: 1.1rem;}.endpoints {background: #f8f9fa;padding: 1.5rem;border-radius: 10px;margin: 2rem 0;text-align: left;}.endpoint {margin: 0.5rem 0;font-family: 'Courier New', monospace;color: #e83e8c;}.btn {display: inline-block;background: #667eea;color: white;padding: 0.8rem 1.5rem;text-decoration: none;border-radius: 5px;margin: 0.5rem;transition: background 0.3s;}.btn:hover {background: #5a6fd8;}.status {margin-top: 1rem;padding: 0.5rem;background: #d4edda;color: #155724;border-radius: 5px;font-size: 0.9rem;}</style>
</head>
<body><div class="container"><h1>Spring Boot 演示应用</h1><p class="subtitle">这是一个简单的 Spring Boot Web 应用演示</p><div class="endpoints"><h3>可用接口:</h3><div class="endpoint">GET /hello - 简单问候</div><div class="endpoint">GET /greet?name=张三 - 个性化问候</div><div class="endpoint">GET /health - 健康检查</div><div class="endpoint">GET /info - 系统信息</div><div class="endpoint">GET / - 首页信息(JSON)</div></div><div><a href="/hello" class="btn">测试 Hello 接口</a><a href="/health" class="btn">健康检查</a><a href="/info" class="btn">系统信息</a><a href="/greet?name=Visitor" class="btn">个性化问候</a></div><div class="status">应用运行正常 | 服务端口: 8080</div></div><script>// 简单的页面交互document.addEventListener('DOMContentLoaded', function() {console.log('Spring Boot 演示应用前端加载完成');});</script>
</body>
</html>
创建和运行步骤
步骤1:创建项目目录结构
# 创建项目根目录
mkdir simple-springboot-demo
cd simple-springboot-demo# 创建源代码目录结构
mkdir -p src/main/java/com/example/demo/controller
mkdir -p src/main/resources/static# 创建所有文件(将上面的内容分别保存到对应文件中)
步骤2:编译和打包
# 在项目根目录(包含pom.xml的目录)执行:# 清理并打包项目
mvn clean package# 或者跳过测试打包
mvn clean package -DskipTests
打包成功后控制台输出:
[INFO] Building jar: /path/to/simple-springboot-demo/target/simple-springboot-demo-1.0.0.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.7.0:repackage (repackage) @ simple-springboot-demo ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
步骤3:运行应用
# 运行打包好的JAR文件
java -jar target/simple-springboot-demo-1.0.0.jar
应用启动成功输出:
=========================================Spring Boot 应用启动成功!访问地址: http://localhost:8080接口测试: http://localhost:8080/hello健康检查: http://localhost:8080/health
=========================================
步骤4:访问测试
打开浏览器访问以下地址:
- 主页: http://localhost:8080/
- Hello接口: http://localhost:8080/hello
- 健康检查: http://localhost:8080/health
- 系统信息: http://localhost:8080/info
- 个性化问候: http://localhost:8080/greet?name=张三
验证应用运行
使用curl测试接口
# 测试首页
curl http://localhost:8080/# 测试hello接口
curl http://localhost:8080/hello# 测试带参数的问候
curl "http://localhost:8080/greet?name=Linux"# 测试健康检查
curl http://localhost:8080/health
预期JSON响应示例
/hello 接口响应:
{"server": "Spring Boot 2.7.0","message": "Hello, this is a simple Spring Boot application!","timestamp": "2025-11-12T10:50:54.048460643"
}
/health 接口响应:
{"service": "simple-springboot-demo","status": "UP","timestamp": "2025-11-12T10:51:05.019648794"
}
生产环境部署
创建启动脚本:start.sh
#!/bin/bash
#########################################
# File Name: start.sh
# Version: V1.0
# Author: Freed
# Date: 2025-11-12 11:16
# Desc: Spring Boot 应用生产环境部署脚本
########################################## 使用绝对路径
APP_HOME="/data/simple-springboot-demo"
APP_NAME="simple-springboot-demo-1.0.0.jar"
JAR_FILE="$APP_HOME/target/$APP_NAME" # Maven 打包后的路径# 如果 target 目录不存在,尝试当前目录
if [ ! -f "$JAR_FILE" ]; thenJAR_FILE="$APP_HOME/$APP_NAME"
fiLOG_DIR="/var/log"
PID_FILE="$APP_HOME/app.pid"
LOG_FILE="$LOG_DIR/springboot-app.log"# 创建日志目录(如果不存在)
mkdir -p $LOG_DIR
touch $LOG_FILE
chmod 666 $LOG_FILE # 确保有写入权限# JVM 参数
JAVA_OPTS="-Xms512m -Xmx1024m -server"
JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=prod"
JAVA_OPTS="$JAVA_OPTS -Dlogging.file.path=$LOG_DIR"
JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"check_environment() {echo "=== 环境检查 ==="# 检查 Javaif ! command -v java &> /dev/null; thenecho "❌ Java 未安装"return 1fiecho "✅ Java: $(java -version 2>&1 | head -1)"# 检查 JAR 文件if [ ! -f "$JAR_FILE" ]; thenecho "❌ JAR 文件不存在: $JAR_FILE"echo "请先执行: mvn clean package"return 1fiecho "✅ JAR 文件: $JAR_FILE"# 检查端口if netstat -lntup | grep -q ":8080"; thenecho "⚠️ 端口 8080 已被占用"return 1fiecho "✅ 端口 8080 可用"return 0
}start_app() {echo "启动应用..."# 环境检查if ! check_environment; thenreturn 1fi# 检查是否已在运行if [ -f $PID_FILE ]; thenPID=$(cat $PID_FILE)if ps -p $PID > /dev/null 2>&1; thenecho "应用已经在运行,PID: $PID"return 1elseecho "清理旧的 PID 文件"rm -f $PID_FILEfifiecho "$(date '+%Y-%m-%d %H:%M:%S') - Starting $APP_NAME" >> $LOG_FILEecho "工作目录: $(pwd)"echo "JAR 文件: $JAR_FILE"echo "JVM 参数: $JAVA_OPTS"# 启动应用(在前台运行以便查看错误)cd $APP_HOMEnohup java $JAVA_OPTS -jar "$JAR_FILE" >> $LOG_FILE 2>&1 &local APP_PID=$!echo $APP_PID > $PID_FILE# 等待应用启动echo "等待应用启动..."sleep 5# 检查进程是否仍在运行if ps -p $APP_PID > /dev/null 2>&1; thenecho "✅ 应用启动成功,PID: $APP_PID"echo "📝 查看日志: tail -f $LOG_FILE"echo "🌐 访问地址: http://localhost:8080"elseecho "❌ 应用启动失败,进程已退出"echo "📝 查看错误日志: tail -20 $LOG_FILE"rm -f $PID_FILEreturn 1fi
}stop_app() {if [ -f $PID_FILE ]; thenPID=$(cat $PID_FILE)echo "停止应用,PID: $PID"kill $PIDsleep 2if ps -p $PID > /dev/null; thenecho "强制终止进程..."kill -9 $PIDfirm -f $PID_FILEecho "应用已停止"elseecho "PID 文件不存在,尝试通过进程名停止"pkill -f "simple-springboot-demo"fi
}case "$1" instart)start_app;;stop)stop_app;;restart)stop_appsleep 3start_app;;status)if [ -f $PID_FILE ]; thenPID=$(cat $PID_FILE)if ps -p $PID > /dev/null; thenecho "✅ 应用运行中,PID: $PID"echo "📊 端口监听:"netstat -lntup | grep $PID || echo "暂无端口监听"elseecho "❌ PID 文件存在但进程不存在"rm -f $PID_FILEfielseecho "❌ 应用未运行"fi;;log)tail -f $LOG_FILE;;env)check_environment;;*)echo "用法: $0 {start|stop|restart|status|log|env}"echo " start - 启动应用"echo " stop - 停止应用" echo " restart - 重启应用"echo " status - 查看状态"echo " log - 查看实时日志"echo " env - 检查环境"exit 1;;
esac
3. Nginx 配置 Spring Boot 反向代理
# 添加 Spring Boot 代理配置
cat >> /etc/nginx/conf.d/tomcat-cluster.conf <<'EOF'# Spring Boot 应用代理
server {listen 8088;server_name api.freedom.cn;location / {proxy_pass http://127.0.0.1:8080;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
EOF# 重新加载 Nginx
nginx -t && systemctl reload nginx
十三、性能与安全优化清单
安全优化
#!/bin/bash
# Tomcat 安全优化脚本(简化版)TOMCAT_HOME="/app/tools/apache-tomcat-9.0.111"# 创建用户和组
getent group tomcat >/dev/null || groupadd tomcat
id tomcat >/dev/null 2>&1 || useradd -s /bin/false -g tomcat -d $TOMCAT_HOME tomcat# 设置权限
chown -R tomcat:tomcat $TOMCAT_HOME
chmod 750 $TOMCAT_HOME/bin/*.sh
chmod 640 $TOMCAT_HOME/conf/*# 安全配置
[ -f "$TOMCAT_HOME/conf/server.xml" ] && sed -i 's/<Connector port="8009"/<!-- &/' $TOMCAT_HOME/conf/server.xml
[ -f "$TOMCAT_HOME/conf/server.xml" ] && sed -i 's/<Server port="8005"/& address="127.0.0.1"/' $TOMCAT_HOME/conf/server.xml# 更新 systemd
[ -f "/etc/systemd/system/tomcat.service" ] && sed -i 's/^User=.*/User=tomcat/; s/^Group=.*/Group=tomcat/' /etc/systemd/system/tomcat.service
systemctl daemon-reload 2>/dev/nullecho "✅ 安全优化完成"
性能优化
#!/bin/bash
# Tomcat 性能优化脚本# 备份原始配置
cp /app/tools/tomcat/conf/server.xml /app/tools/tomcat/conf/server.xml.bak# 优化 server.xml 连接器配置
cat > /tmp/server_optimized.xml <<'EOF'
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443"maxThreads="400"minSpareThreads="50"maxConnections="10000"acceptCount="200"compression="on"compressionMinSize="1024"compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json"URIEncoding="UTF-8"server="Nginx"enableLookups="false"/>
EOF# 应用优化配置(需要手动替换或使用 sed 进行精确修改)
echo "请手动将优化后的 Connector 配置应用到 /app/tools/tomcat/conf/server.xml"# JVM 优化参数
cat >> /etc/systemd/system/tomcat.service <<'EOF'# JVM 性能优化
Environment="CATALINA_OPTS=-Xms1024M -Xmx1024M -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ParallelRefProcEnabled -XX:+UnlockExperimentalVMOptions -XX:+DoEscapeAnalysis -XX:ParallelGCThreads=4 -XX:ConcGCThreads=2 -XX:G1HeapRegionSize=32m -XX:InitiatingHeapOccupancyPercent=45 -XX:+PrintGC -XX:+PrintGCDetails -Xloggc:/var/log/tomcat_gc.log"
EOFsystemctl daemon-reload
systemctl restart tomcatecho "性能优化完成"
十四、常见问题与解决方案
问题排查指南
#!/bin/bash
# Tomcat 问题排查工具echo "=== Tomcat 问题诊断 ==="# 1. 检查服务状态
echo "1. 检查服务状态:"
systemctl status tomcat --no-pager -l# 2. 检查端口占用
echo -e "\n2. 检查端口占用:"
netstat -tulnp | grep :8080 || echo "端口 8080 未监听"# 3. 检查 Java 进程
echo -e "\n3. Java 进程检查:"
ps aux | grep java | grep -v grep# 4. 检查日志错误
echo -e "\n4. 最近错误日志:"
tail -50 /app/tools/tomcat/logs/catalina.out | grep -i error | tail -10# 5. 检查磁盘空间
echo -e "\n5. 磁盘空间检查:"
df -h /app /var# 6. 检查内存使用
echo -e "\n6. 内存使用检查:"
free -h# 7. 环境变量检查
echo -e "\n7. 环境变量检查:"
echo "JAVA_HOME: $JAVA_HOME"
echo "PATH: $PATH"echo -e "\n=== 诊断完成 ==="
快速重启脚本
#!/bin/bash
# Tomcat 快速重启脚本echo "正在停止 Tomcat..."
systemctl stop tomcat# 确保进程停止
sleep 3
pkill -f tomcatecho "清理临时文件..."
rm -rf /app/tools/tomcat/work/Catalina/localhost/*
rm -rf /app/tools/tomcat/temp/*echo "启动 Tomcat..."
systemctl start tomcatecho "等待服务启动..."
sleep 10# 检查启动状态
if systemctl is-active --quiet tomcat; thenecho "✅ Tomcat 重启成功"
elseecho "❌ Tomcat 重启失败,请检查日志"journalctl -u tomcat --no-pager -l --lines=20
fi
参考资料
- Apache Tomcat 官网
- OpenJDK 官方网站
- Amazon Corretto 下载页
- Spring Boot 官方文档
- Nginx 官方文档
