【Java】踩坑实录:Spring Boot + Nginx 本地部署404终极排查:从80端口被占用到配置生效全流程

前言

在搭建前后端分离项目本地部署环境 时,遇到了经典的"Nginx代理访问404"问题:Spring Boot后端(8106端口)启动正常,Nginx看似启动成功,但访问localhost始终返回404,甚至出现bind() to 0.0.0.0:80 failed (10013)启动报错。

经过多轮排查,最终定位了端口占用配置路径进程重启三大核心坑点。本文将完整还原排查过程与解决方案,希望能帮到同样踩坑的小伙伴,少走弯路。

关键在于通过查看nginx-1.28.0\logs\error.log的日志,发现了是端口占用问题。

一、问题背景

项目环境

  • 后端:Spring Boot 2.6.2,运行端口8106,接口前缀/app/

  • 前端:静态资源打包后存放于D:\reference-project\package\front\nginx-1.28.0\html\public

  • 代理:Nginx 1.28.0(Windows版),计划代理前端静态资源+后端接口

  • 目标:访问localhost打开前端页面,且前端能正常调用后端接口

异常现象

  1. Spring Boot后端日志正常,访问http://localhost:8106/app/xxx能正常返回接口数据;

  2. Nginx启动时提示bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)

  3. 强行启动Nginx后,访问localhost返回HTTP Error 404. The requested resource is not found.

  4. 确认public目录下存在index.html,排除静态资源缺失问题。

二、核心排查过程(按优先级排序)

步骤1:验证静态资源有效性(排除基础问题)

首先确认前端静态资源路径无误,打开文件资源管理器,核对路径D:\reference-project\package\front\nginx-1.28.0\html\public下存在index.htmlstatic等核心文件,排除"文件缺失导致404"的基础问题。

步骤2:定位Nginx启动报错核心原因------80端口被系统占用

通过netstat -ano | findstr :80命令查看端口占用,发现[::]:80的监听进程PID为4,这是Windows的System系统进程

关键知识点:PID 4 占用80端口的本质

PID 4对应的是Windows内核级的HTTP.sys驱动(Windows HTTP服务),该服务支撑IIS、网络打印机共享、WinRM远程管理等功能,会默认占用80端口。此时直接启动Nginx监听80端口,必然触发10013权限禁止错误。

步骤3:修改端口后仍404------排查配置与重启问题

将Nginx监听端口改为8080后,访问localhost:8080仍报404,核心原因有二:

  1. 配置未生效 :仅修改端口,未使用绝对路径配置静态资源,且未彻底重启Nginx;

  2. 访问地址错误 :改端口后未在浏览器中添加端口号,仍访问localhost(默认80端口)。

三、终极解决方案(可直接复制落地)

结合本次问题,最终采用**"修改Nginx配置 + 彻底重启进程 + 验证端口访问"**的方案,兼顾开发便利性与系统服务安全性(不停止Windows HTTP服务)。

方案1:修改Nginx核心配置(nginx.conf)

打开nginx-1.28.0\conf\nginx.conf,替换server块配置,重点解决静态资源路径端口冲突SPA路由接口代理四大问题:

nginx 复制代码
# Nginx核心配置(适配Windows本地开发)
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    # 核心服务配置
    server {
        listen       8080;  # 避开80端口冲突,改为8080
        server_name  localhost;
        charset utf-8;

        # 1. 前端静态资源代理(关键:可使用绝对路径  root D:/reference-project/package/front/nginx-1.28.0/)
        location / {
            root html/public;  
            index index.html index.htm;
            try_files $uri $uri/ /index.html;  # 支持SPA路由刷新,避免子路径404
        }

        # 2. 后端接口代理(匹配前端请求前缀/app/)
        location /app/ {
            proxy_pass http://localhost:8106/app/;  # 代理到Spring Boot后端
            proxy_redirect  off;
            # 传递请求头,解决后端获取客户端IP、Host异常问题
            proxy_set_header Host $host;
            proxy_set_header X-real-ip $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        # 错误页面配置
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

方案2:管理员权限彻底重启Nginx(避免进程残留)

Windows下Nginx进程易残留,导致新配置无法生效,必须以管理员身份执行以下命令:

bash 复制代码
# 1. 进入Nginx安装目录
cd D:\reference-project\package\hzb-front\nginx-1.28.0

# 2. 强制杀死所有Nginx进程(核心:避免残留)
taskkill /f /im nginx.exe

# 3. 重新启动Nginx
nginx

方案3:验证部署结果

  1. 前端页面验证 :浏览器访问http://localhost:8080,成功加载前端页面;

  2. 后端接口验证 :前端调用接口(如/app/user/info),能正常获取后端返回数据;

  3. 日志验证 :查看nginx-1.28.0\logs\error.log,无任何报错信息,说明部署成功。

四、拓展补充:两种端口解决方案对比

解决方案 操作方式 适用场景 优缺点
改Nginx端口(本文方案) 将监听端口改为8080/8090等 本地开发、无需使用80端口 优点:不影响系统服务;缺点:访问需加端口号
释放80端口 停止Windows HTTP服务(net stop http 生产部署、必须使用80端口 优点:可直接访问localhost;缺点:可能影响IIS、网络打印机等功能

提示:本地开发优先选择"改Nginx端口",生产环境若需使用80端口,可先评估系统服务依赖,再执行net stop http停止服务。

五、Windows下Nginx本地部署核心避坑点

  1. 路径坑 :Windows下配置root必须使用绝对路径/\\分隔),相对路径易因启动目录不同导致文件找不到;

  2. 端口坑:1024以下端口(如80)需管理员权限,且易被系统服务占用,开发建议使用8080/8888等端口;

  3. 重启坑 :修改配置后,必须先taskkill强制杀死进程,再启动,仅用nginx -s reload可能因进程残留失效;

  4. SPA坑 :前端为Vue/React等单页应用时,必须添加try_files $uri $uri/ /index.html;,否则路由刷新会404。

六、总结

本次404问题的核心逻辑是:80端口被系统占用 → Nginx启动失败/配置未生效 → 静态资源无法被正确代理 → 访问报404

(注:文档部分内容由 AI 生成)

相关推荐
6+h2 小时前
【Spring】AOP核心之原始对象与代理对象
java·python·spring
君爱学习2 小时前
SpringCloud-微服务拆分
java
礼拜天没时间.2 小时前
力扣热题100实战 | 第25期:K个一组翻转链表——从两两交换到K路翻转的进阶之路
java·算法·leetcode·链表·递归·链表反转·k个一组翻转链表
y = xⁿ2 小时前
【从零开始学习Redis|第四篇】从底层理解缓存问题:雪崩、击穿、穿透与一致性设计
java·redis·学习·缓存
江湖有缘2 小时前
本地化JSON 处理新方案:基于 Docker的JSON Hero部署全记录
java·docker·json
御坂10101号2 小时前
「2>&1」是什么意思?半个世纪的 Unix 谜题
java·数据库·bash·unix
韩立学长2 小时前
基于Springboot校园志愿者服务平台77pz7812(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
Java基基3 小时前
Spring让Java慢了30倍,JIT、AOT等让Java比Python快13倍,比C慢17%
java·开发语言·后端·spring
future02103 小时前
Spring AOP核心机制:代理与拦截揭秘
java·开发语言·spring·面试·aop