本文档整理了在 Ubuntu 22.04+ 系统上使用 aptitude 部署完整 Java Web 环境的步骤,包含 Nginx、JDK 17、Redis 和 MySQL 8 的安装、配置、SSL 证书、跨域配置及常用命令。

文档说明

版本 日期 说明
1.0 2026-03-22 初始版本,包含基础环境部署
1.1 2026-03-22 添加 SSL 证书配置章节
1.2 2026-03-22 添加跨域配置章节
1.3 2026-03-22 优化文档结构,增加目录导航

适用场景

本文档适用于以下场景:

  • Web 服务器部署:Nginx 作为 Web 服务器和反向代理
  • Java 应用部署:JDK 17 运行 Java 应用
  • 缓存服务部署:Redis 作为缓存数据库
  • 关系型数据库部署:MySQL 8 作为关系型数据库
  • HTTPS 配置:SSL 证书配置,支持 HTTPS
  • 跨域配置:Nginx 跨域配置,支持前端应用访问

技术栈

组件 版本 说明
Ubuntu 22.04+ 操作系统
Nginx 最新稳定版 Web 服务器和反向代理
JDK 17 Java 开发和运行环境
Redis 最新稳定版 缓存和数据库
MySQL 8.0 关系型数据库
SSL Let’s Encrypt 免费 SSL 证书

目录

第一部分:环境部署

第二部分:Nginx 高级配置

第三部分:服务管理与安全


环境准备

1
2
3
4
5
# 更新包索引
sudo aptitude update

# 安装必要工具
sudo aptitude install curl gnupg2 ca-certificates lsb-release ubuntu-keyring -y

安装 Nginx

方法一:使用 aptitude 安装(Ubuntu 默认仓库)

1
2
3
4
5
6
7
8
# 更新包索引
sudo aptitude update

# 安装 Nginx
sudo aptitude install nginx -y

# 检查版本
nginx -v

方法二:安装官方最新稳定版(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
# 添加 Nginx 官方签名密钥
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

# 添加官方仓库(稳定版)
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

# 更新并安装
sudo aptitude update
sudo aptitude install nginx -y

启动并验证服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启动 Nginx
sudo systemctl start nginx

# 设置开机自启
sudo systemctl enable nginx

# 检查状态
sudo systemctl status nginx

# 测试配置文件语法
sudo nginx -t

# 查看监听端口
sudo ss -tlnp | grep nginx

安装 JDK 17

方法一:使用 aptitude 安装 OpenJDK 17(推荐)

1
2
3
4
5
6
7
8
# 更新包索引
sudo aptitude update

# 安装 OpenJDK 17 开发套件(包含编译器 javac)
sudo aptitude install openjdk-17-jdk -y

# 或者仅安装运行时环境(JRE,不包含编译器)
sudo aptitude install openjdk-17-jre -y

方法二:安装 Oracle JDK 17(官方闭源版本)

1
2
3
4
5
# 下载 Oracle JDK 17
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.deb

# 使用 aptitude 安装
sudo aptitude install ./jdk-17_linux-x64_bin.deb -y

验证安装

1
2
3
4
5
6
7
8
9
# 检查 Java 版本
java -version

# 检查编译器版本
javac -version

# 检查安装路径
which java
readlink -f $(which java)

配置环境变量(可选)

1
2
3
4
5
6
7
8
9
10
11
12
# 编辑环境变量文件
sudo nano /etc/profile.d/jdk.sh

# 添加以下内容:
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$PATH:$JAVA_HOME/bin

# 使配置生效
source /etc/profile.d/jdk.sh

# 验证环境变量
echo $JAVA_HOME

多版本管理(如有多个JDK)

1
2
3
4
5
6
7
8
# 查看已安装的 Java 版本
sudo update-alternatives --config java

# 查看已安装的 javac 版本
sudo update-alternatives --config javac

# 设置默认版本
sudo update-alternatives --config java

安装 Redis

方法一:使用 aptitude 安装(推荐)

1
2
3
4
5
# 更新包索引
sudo aptitude update

# 安装 Redis
sudo aptitude install redis-server -y

方法二:使用官方仓库安装(获取最新版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装依赖
sudo aptitude install lsb-release curl gpg -y

# 添加 Redis 官方 GPG 密钥
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg

# 添加官方仓库
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list

# 更新并安装
sudo aptitude update
sudo aptitude install redis -y

启动并验证服务

1
2
3
4
5
6
7
8
9
10
11
12
# 启动 Redis 服务
sudo systemctl start redis-server

# 设置开机自启
sudo systemctl enable redis-server

# 检查状态
sudo systemctl status redis-server

# 测试连接
redis-cli ping
# 预期输出: PONG

设置密码

方法一:通过配置文件设置(持久化,推荐)

1
2
3
4
5
6
7
8
9
10
# 编辑配置文件
sudo nano /etc/redis/redis.conf

# 找到并修改以下行(去掉注释并设置密码)
requirepass your_strong_password_here

# 保存并退出 (Ctrl+O, Enter, Ctrl+X)

# 重启 Redis 生效
sudo systemctl restart redis-server

方法二:运行时动态设置(立即生效,重启后失效)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 连接到 Redis
redis-cli

# 设置新密码
127.0.0.1:6379> CONFIG SET requirepass "your_new_password"
OK

# 验证密码已设置
127.0.0.1:6379> CONFIG GET requirepass

# 认证(当前连接需要重新认证)
127.0.0.1:6379> AUTH your_new_password
OK

# 将配置持久化到配置文件(可选)
127.0.0.1:6379> CONFIG REWRITE
OK

使用密码连接 Redis

1
2
3
4
5
6
7
8
9
10
11
# 方式 1:命令行带密码
redis-cli -a "your_password"

# 方式 2:连接后认证
redis-cli
127.0.0.1:6379> AUTH your_password
OK

# 方式 3:使用环境变量(避免密码暴露在命令历史)
export REDISCLI_AUTH="your_password"
redis-cli

安装 MySQL 8

方法一:使用 aptitude 安装(Ubuntu 默认仓库)

1
2
3
4
5
6
7
8
# 更新包索引
sudo aptitude update

# 安装 MySQL 8(Ubuntu 22.04+ 默认包含 MySQL 8.0)
sudo aptitude install mysql-server -y

# 检查安装的版本
mysql --version

方法二:安装官方最新版(推荐)

1
2
3
4
5
6
7
8
9
10
11
# 下载 MySQL 官方 APT 配置包
wget https://dev.mysql.com/get/mysql-apt-config_0.8.30-1_all.deb

# 安装配置包(会弹出交互界面选择版本)
sudo dpkg -i mysql-apt-config_0.8.30-1_all.deb

# 更新包索引
sudo aptitude update

# 安装 MySQL 8
sudo aptitude install mysql-server -y

启动并验证服务

1
2
3
4
5
6
7
8
# 检查服务状态
sudo systemctl status mysql

# 确保开机自启
sudo systemctl enable mysql

# 查看监听端口
sudo ss -tlnp | grep mysql

设置 root 密码

场景一:首次安装后设置密码(推荐方式)

MySQL 8 默认使用 auth_socket 认证,root 用户无需密码即可通过系统 root 登录:

1
2
3
4
5
6
7
# 使用系统 root 直接登录(无需密码)
sudo mysql

# 在 MySQL 命令行中设置密码
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'YourStrongPassword123!';
FLUSH PRIVILEGES;
EXIT;

场景二:忘记密码,需要重置

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
# 1. 停止 MySQL 服务
sudo systemctl stop mysql

# 2. 创建临时目录并设置权限
sudo mkdir -p /var/run/mysqld
sudo chown mysql:mysql /var/run/mysqld

# 3. 以跳过权限表方式启动 MySQL
sudo mysqld_safe --skip-grant-tables --skip-networking &

# 4. 无密码登录
mysql -u root

# 5. 在 MySQL 8 中重置密码
USE mysql;
UPDATE user SET authentication_string=null WHERE User='root';
FLUSH PRIVILEGES;

# 6. 设置新密码
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'YourNewPassword123!';
FLUSH PRIVILEGES;
EXIT;

# 7. 停止安全模式进程并正常启动
sudo killall -9 mysqld
sudo systemctl start mysql

# 8. 验证新密码
mysql -u root -p

场景三:使用 init 文件方法(更安全)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 创建初始化文件
echo "ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword123!';" | sudo tee /var/tmp/mysql-init

# 2. 停止 MySQL
sudo systemctl stop mysql

# 3. 使用 init 文件启动
sudo mysqld --init-file=/var/tmp/mysql-init --daemonize

# 4. 正常重启
sudo systemctl restart mysql

# 5. 删除临时文件
sudo rm /var/tmp/mysql-init

# 6. 验证
mysql -u root -p

安全配置

1
2
# 运行安全脚本(会提示设置密码策略、移除匿名用户等)
sudo mysql_secure_installation

完整部署脚本

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
#!/bin/bash
set -e

echo "=========================================="
echo " Ubuntu 完整环境部署脚本"
echo " 包含: Redis + JDK 17 + MySQL 8 + Nginx"
echo "=========================================="

# 更新系统
echo "[1/6] 更新包索引..."
sudo aptitude update

# 安装 Redis
echo "[2/6] 部署 Redis..."
sudo aptitude install redis-server -y
sudo systemctl enable redis-server
sudo systemctl start redis-server
redis-cli ping

# 安装 JDK 17
echo "[3/6] 部署 JDK 17..."
if [ -f "/home/ubuntu/src/jdk-17.0.18_linux-x64_bin.deb" ]; then
cd /home/ubuntu/src
sudo dpkg -i jdk-17.0.18_linux-x64_bin.deb
sudo aptitude install -f -y
else
sudo aptitude install openjdk-17-jdk -y
fi
java -version

# 安装 MySQL 8
echo "[4/6] 部署 MySQL 8..."
sudo aptitude install mysql-server -y
sudo systemctl enable mysql
sudo systemctl start mysql

# 设置 MySQL root 密码
MYSQL_ROOT_PASS="Root@123456"
sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '${MYSQL_ROOT_PASS}'; FLUSH PRIVILEGES;" 2>/dev/null || \
sudo mysql -e "CREATE USER IF NOT EXISTS 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '${MYSQL_ROOT_PASS}'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION; FLUSH PRIVILEGES;"

# 安装 Nginx
echo "[5/6] 部署 Nginx..."
sudo aptitude install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx

# 验证所有服务
echo ""
echo "=========================================="
echo " 部署完成,服务状态验证:"
echo "=========================================="
echo -n "Redis: "; redis-cli ping 2>/dev/null || echo "未运行"
echo -n "MySQL: "; mysql -u root -p${MYSQL_ROOT_PASS} -e "SELECT 1;" >/dev/null 2>&1 && echo "运行正常" || echo "需要检查"
echo -n "Nginx: "; curl -s -o /dev/null -w "%{http_code}" http://localhost | grep -q "200\|403" && echo "运行正常 (HTTP $(curl -s -o /dev/null -w "%{http_code}" http://localhost))" || echo "未运行"
echo -n "Java: "; java -version 2>&1 | head -1

echo ""
echo "=========================================="
echo " 默认配置信息:"
echo "=========================================="
echo "Redis: 无密码 / 端口 6379"
echo "MySQL: root / ${MYSQL_ROOT_PASS} / 端口 3306"
echo "Nginx: 端口 80 / 配置文件 /etc/nginx/nginx.conf"
echo "JDK 17: $(readlink -f $(which java) 2>/dev/null || echo '已安装')"
echo "=========================================="

配置示例

Nginx 反向代理到 Java 应用(Spring Boot)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 编辑配置文件
sudo nano /etc/nginx/sites-available/default

# 添加以下内容
server {
listen 80;
server_name your-domain.com;

location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
}

# 测试并重载配置
sudo nginx -t
sudo systemctl reload nginx

Nginx 负载均衡配置

1
2
3
4
5
6
7
8
9
10
11
12
upstream backend {
server 127.0.0.1:8080 weight=5;
server 127.0.0.1:8081 weight=5;
server 127.0.0.1:8082 backup;
}

server {
listen 80;
location / {
proxy_pass http://backend;
}
}

Redis 安全配置

1
2
3
4
5
6
7
# 在 /etc/redis/redis.conf 中确保
bind 127.0.0.1 ::1

# 禁用危险命令(可选)
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG "CONFIG_admin_only"

服务管理速查

服务 启动 停止 重启 状态
Nginx sudo systemctl start nginx sudo systemctl stop nginx sudo systemctl restart nginx sudo systemctl status nginx
MySQL sudo systemctl start mysql sudo systemctl stop mysql sudo systemctl restart mysql sudo systemctl status mysql
Redis sudo systemctl start redis-server sudo systemctl stop redis-server sudo systemctl restart redis-server sudo systemctl status redis-server

提示:所有服务均已配置开机自启,服务器重启后会自动启动。


防火墙配置

1
2
3
4
5
6
7
8
9
# 允许 HTTP/HTTPS
sudo ufw allow 'Nginx Full'

# 或单独允许端口
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# 查看状态
sudo ufw status

SSL 证书配置

安装 acme.sh

1
2
3
4
5
6
7
8
# 安装 acme.sh
curl https://get.acme.sh | sh -s email=my@example.com

# 重新加载 shell 配置
source ~/.bashrc

# 查看 acme.sh 版本
acme.sh --version

申请 SSL 证书

方法一:Webroot 方式(推荐)

1
2
3
4
5
6
7
8
# 使用 Webroot 方式申请证书
acme.sh --issue -d your-domain.com -d www.your-domain.com --webroot /var/www/html

# 安装证书到 Nginx
acme.sh --install-cert -d your-domain.com \
--key-file /etc/nginx/ssl/private.key \
--fullchain-file /etc/nginx/ssl/fullchain.crt \
--reloadcmd "systemctl reload nginx"

方法二:Stand-alone 方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 停止 Nginx
sudo systemctl stop nginx

# 使用 Stand-alone 方式申请证书
acme.sh --issue --standalone -d your-domain.com -d www.your-domain.com

# 安装证书
acme.sh --install-cert -d your-domain.com \
--key-file /etc/nginx/ssl/private.key \
--fullchain-file /etc/nginx/ssl/fullchain.crt \
--reloadcmd "systemctl reload nginx"

# 重启 Nginx
sudo systemctl start nginx

方法三:DNS 方式(适用于泛域名)

1
2
3
4
5
6
7
8
# 使用 DNS 方式申请泛域名证书
acme.sh --issue --dns dns_provider -d your-domain.com -d *.your-domain.com

# 安装证书
acme.sh --install-cert -d your-domain.com \
--key-file /etc/nginx/ssl/private.key \
--fullchain-file /etc/nginx/ssl/fullchain.crt \
--reloadcmd "systemctl reload nginx"

Nginx SSL 配置(高安全性)

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
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name your-domain.com www.your-domain.com;

# 强制重定向到 HTTPS
return 301 https://$server_name$request_uri;
}

# HTTPS 配置
server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;

# SSL 证书路径
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/private.key;

# SSL 协议配置(高安全性)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# SSL 会话配置
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;

# DNS 解析(用于 OCSP Stapling)
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# HSTS 头(可选,生产环境建议启用)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

# 根目录配置
location / {
root /var/www/html;
index index.html index.htm;
}

# 反向代理配置
location /api/ {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
}

Nginx SSL 配置(兼容性好)

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
# 如果需要兼容较老的客户端,可以使用以下配置
server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;

# SSL 证书路径
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/private.key;

# SSL 协议配置(兼容性好)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:MEDIUM:!aNULL:!MD5:!RC4;
ssl_prefer_server_ciphers on;

# SSL 会话配置
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;

# DNS 解析(用于 OCSP Stapling)
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# HSTS 头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# 根目录配置
location / {
root /var/www/html;
index index.html index.htm;
}
}

证书自动续期

1
2
3
4
5
6
7
8
9
10
11
12
13
# acme.sh 默认会自动续期证书,可以通过以下命令检查

# 查看证书列表
acme.sh --list

# 手动续期证书
acme.sh --renew -d your-domain.com

# 强制续期证书
acme.sh --renew -d your-domain.com --force

# 测试续期(不实际续期)
acme.sh --renew -d your-domain.com --test

证书管理命令

1
2
3
4
5
6
7
8
9
10
11
# 查看证书详情
acme.sh --list

# 删除证书
acme.sh --remove -d your-domain.com

# 手动更新 acme.sh
acme.sh --upgrade

# 查看 acme.sh 日志
tail -f ~/.acme.sh/acme.sh.log

安全建议

1. 生成强密码

1
openssl rand -base64 32

2. MySQL 安全配置

  • 使用强密码(至少 12 位,包含大小写字母、数字和特殊字符)
  • 限制 root 用户远程访问
  • 移除匿名用户
  • 运行 mysql_secure_installation 进行安全加固

3. Redis 安全配置

  • 绑定本地地址(默认已配置)
  • 设置强密码
  • 禁用危险命令(FLUSHDB、FLUSHALL、CONFIG)
  • 防火墙限制访问

4. JDK 安全配置

  • 定期更新到最新版本
  • 配置 Java 安全策略
  • 限制 JMX 和 JDP 远程访问

常见问题

问题 1:aptitude 无法安装本地 deb 包

aptitude 默认只搜索仓库中的包,不会自动识别本地 deb 文件。

解决方案:

1
2
3
4
5
6
# 方法一:使用 dpkg 安装(推荐)
sudo dpkg -i jdk-17.0.18_linux-x64_bin.deb
sudo aptitude install -f -y

# 方法二:使用 apt 安装本地 deb 包
sudo apt install ./jdk-17.0.18_linux-x64_bin.deb -y

问题 2:MySQL 8 认证插件兼容性

MySQL 8.0 默认使用 caching_sha2_password 认证插件,如需兼容旧版 PHP 等客户端,可改为 mysql_native_password

1
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

Nginx 跨域配置

OPTIONS 请求处理

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
# 在 server 块中添加 OPTIONS 请求处理
server {
listen 80;
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;

# SSL 证书配置(HTTPS 时需要)
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/private.key;

# CORS 预检请求处理
location / {
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
add_header Access-Control-Max-Age "86400" always;
return 204;
}

# 其他请求的 CORS 头
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
}

# 反向代理配置(适用于 API 服务)
location /api/ {
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
add_header Access-Control-Max-Age "86400" always;
return 204;
}

# 其他请求的 CORS 头
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;

proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
}

更安全的跨域配置(推荐)

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
# 使用变量控制跨域,避免重复添加头
map $http_origin $cors_origin {
default "";
"~^https?://(your-domain\.com|www\.your-domain\.com)($|/)" $http_origin;
}

server {
listen 80;
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;

# SSL 证书配置
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/private.key;

# CORS 配置
location / {
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
add_header Access-Control-Max-Age "86400" always;
add_header Content-Length "0" always;
add_header Content-Type "text/plain, charset=utf-8" always;
return 204;
}

# 添加 CORS 头
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
}

location /api/ {
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
add_header Access-Control-Max-Age "86400" always;
add_header Content-Length "0" always;
add_header Content-Type "text/plain, charset=utf-8" always;
return 204;
}

# 添加 CORS 头
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;

proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
}

多域名跨域配置

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
# 支持多个域名的跨域配置
map $http_origin $cors_origin {
default "";
"~^https?://(your-domain\.com|www\.your-domain\.com)$" $http_origin;
"~^https?://(app\.your-domain\.com)$" $http_origin;
"~^https?://(admin\.your-domain\.com)$" $http_origin;
}

server {
listen 80;
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com app.your-domain.com admin.your-domain.com;

# SSL 证书配置
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/private.key;

location / {
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
add_header Access-Control-Max-Age "86400" always;
add_header Content-Length "0" always;
add_header Content-Type "text/plain, charset=utf-8" always;
return 204;
}

# 添加 CORS 头
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always;
}
}

跨域配置说明

配置项 说明
Access-Control-Allow-Origin 允许访问的域名,* 表示允许所有,推荐指定具体域名
Access-Control-Allow-Methods 允许的 HTTP 方法
Access-Control-Allow-Headers 允许的请求头
Access-Control-Expose-Headers 暴露给浏览器的响应头
Access-Control-Max-Age 预检请求缓存时间(秒)
OPTIONS 预检请求方法,返回 204 状态码

测试跨域配置

1
2
3
4
5
6
7
8
# 使用 curl 测试 OPTIONS 请求
curl -X OPTIONS -H "Origin: https://your-domain.com" -H "Access-Control-Request-Method: POST" https://your-domain.com/api/ -v

# 使用 curl 测试 GET 请求
curl -H "Origin: https://your-domain.com" https://your-domain.com/api/ -v

# 在浏览器中测试
# 打开开发者工具,查看 Network 标签页中的请求头和响应头

总结

本文档整理了在 Ubuntu 22.04+ 系统上部署完整 Java Web 环境的步骤,包含以下组件:

  • Nginx:高性能 Web 服务器和反向代理
  • JDK 17:Java 开发和运行环境(LTS 版本)
  • Redis:高性能缓存和数据库
  • MySQL 8:关系型数据库

所有组件均支持通过 aptitude 包管理器安装,并提供了详细的配置和安全建议。