上集:一个前端的血泪复仇记 —— 静态部署的胜利
“我只是想部署一个小项目,结果干翻了Spring Security、Next.js 和 AI —— 三个加起来至少值我两天命。”
话说有一天,我朋友搭了一个小系统,前后端分离,说大不大,说小不小。后端Spring Boot 3.4.5,前端Next.js 15。开发时他们自我感觉良好,分层清晰,接口明了,Node起服务,Spring管API,一切皆优雅。
然而,当要部署上线时,他们懵了。
Azure上已经通过GitHub Actions成功部署好了后端jar包,但前端还在本地嗷嗷叫。老板催着要结果,可老板哪会折腾前端部署?你还得教他怎么写Actions脚本、怎么设置Node环境、怎么指定输出目录……天知道你一说完他会不会当场升天。
这时候我一拍大腿:
“何必呢?这项目没几个页面,又不需要SSR,咱就静态导出,然后把前端生成的HTML+JS直接丢进Spring Boot的static目录不就完了?jar包一启动,前后端全搞定,老板连指都不用动!”
第一难关:Spring Security 发疯了!
你以为这样就结束了?不,地狱的大门这才刚刚打开。
我照着Next.js的文档老老实实 npx next export
,拷进resources/static/
目录,打jar,跑起来,打开浏览器:403 Forbidden。
不是404,不是500,是403。意思是你这请求我知道,但我就是不让你进。
我立刻意识到:是Spring Security出手了。
点开日志,一行熟悉的输出迎面而来:
Securing GET /
Http403ForbiddenEntryPoint: Pre-authenticated entry point called. Rejecting access
这熟悉的中世纪防火墙味道……果然是你,Security!
于是我翻出SecurityConfig
,一看默认策略是 .anyRequest().authenticated()
,只放行了/api/**
和 /public/**
。而我那可怜的index.html,连个像样的api都不是,当然被一棍子拍死在门外。
我没有头铁上去一个个添加 /index.html
、/*.js
、/*.css
……那样太低效。正确方式其实就两个字:放行。
于是我重新配置了SecurityConfig.java
,使用精简清晰的策略:只对 /api/**
做权限控制,其余一律放行。
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/**").authenticated()
.anyRequest().permitAll()
配合上另一个核心配置——WebConfig.java
中精细处理静态资源和前端路径:
if (resourcePath.contains(".")) return null; // 静态资源请求
if (resourcePath.startsWith("api/")) return null; // 后端接口
return new ClassPathResource("/static/index.html"); // 其他全部交给前端路由
部署、启动、访问:Boom,终于进来了。
第二难关:前端路由全军覆没
我刚准备喝口水庆祝一下,结果点击跳转到 /admin/login
页面时,界面啪地一下变白了。
刷新页面,仍然白屏。
看着那沉默如谜的浏览器窗口,我仿佛听见了它在说:
“你静态部署的SPA里根本没这个路径。”
于是我开始搜索、试验,AI这时候又开始滔滔不绝:
“写个FrontendController吧,用@Forward转发所有路径到index.html!”
我信了。然后一秒钟内,部署的服务陷入了前端路由的死循环:什么都跳转,什么都不对。
点击任何路由按钮,都不是你想去的页面,而是index本尊笑着再次出现。
于是我彻底扔掉了FrontendController那一套。
你用静态导出的Next.js,其实每一个页面路径,都已经被导出成了真正的HTML文件!比如 /admin/login
对应的就是 admin/login/index.html
,这些文件真实地存在于 out/
目录中。只要你把它们原封不动地复制进Spring Boot的 static/
目录中,路径匹配得上,页面自然就出来了,根本不需要靠 index.html 来做路由跳转!
AI死活跟我说,“你这个前端还是SPA,要靠 index.html 来初始化页面、再用JS切换路由”,我反复回怼:“你是不是没搞清楚静态导出是什么意思?”
最后我干脆截图,把 Next.js 导出的每个页面的 index.html 全部拍给它看,我说你看,是不是每个页面都有?每个URL其实就是对应一个静态路径,压根不需要搞什么index跳转那一套。
它这才哑口无言,终于认同我的方案,把 WebConfig 改成现在这个样子 —— 静态资源自己找,找不到再跳 index,而不是一上来就全部丢给 index 去兜底。
所以问题的根源是:不该试图用Controller去理解前端的路由,也不能拿SPA框架的假设来套用静态导出逻辑。
正确姿势是:
- 让 WebConfig 的
ResourceHandler
处理静态文件匹配 - 只放过那些真的访问不到的页面给 index.html
- 更重要的是:你要相信文件系统,而不是JS路由器!
配置定了,页面能跳,静态能拿,接口能调,世界终于恢复了秩序。
小结:写给还在挣扎的小项目开发者
- 前后端分离是一种美梦,但对小项目而言,它可能是场噩梦
- 能静态部署的,就别搭两个服务了,咱不卷
- AI是个很棒的助手,但它不懂项目上下文,更不会给你抹眼泪
- 不要让AI拉着你进坑,它会笑着劝你用Controller转发一切,然后带你走向死循环
- 最靠谱的办法,永远是你亲眼看清 log,亲手写对 config,亲自试出通路
下集我会继续讲完整的构建流程、打包命令、静态导出配置、最终Security+WebConfig的全代码。并带你避开更多AI建议里那些"听起来合理,做出来崩盘"的经典误区。
别急,下一章我们见真章。
相关文章:
上集:一个前端的血泪复仇记 —— 静态部署的胜利
“我只是想部署一个小项目,结果干翻了Spring Security、Next.js 和 AI —— 三个加起来至少值我两天命。” 话说有一天,我朋友搭了一个小系统,前后端分离,说大不大,说小不小。后端Spring Boot 3.4.5,前端Ne…...
网络流量分析 | Zeek(上)
介绍 Zeek 是一个开源且商用的网络监控和流量分析工具,许多的运维人员将 Zeek 作为网络安全监控器(Network Security Monitor,NSM),以支持可疑或恶意活动的调查。在安全领域之外,Zeek 还可被用于各种流量分…...
Unity3D仿星露谷物语开发44之收集农作物
1、目标 在土地中挖掘后,洒下种子后逐渐成长,然后使用篮子收集成熟后的农作物,工具栏中也会相应地增加该农作物。 2、修改CropStandard的参数 Assets -> Prefabs -> Crop下的CropStandard,修改其Box Collider 2D的Size(Y…...
AUTOSAR图解==>AUTOSAR_SRS_WatchdogDriver
AUTOSAR 看门狗驱动 (Watchdog Driver) 详解 AUTOSAR基础软件模块之看门狗驱动技术分析 目录 概述 1.1 看门狗驱动的作用 1.2 适用范围架构设计 2.1 总体架构 2.2 内部结构 2.3 接口设计功能实现 3.1 初始化和模式切换 3.2 状态管理 3.3 外部看门狗支持配置参数 4.1 核心配置项…...
Fidder基本操作
1.抓取https请求 Fidder默认不能抓取https请求,我们必须通过相应的设置才能抓取https请求 1.选择tools下的option 2.选择https选项,并且勾选下面的选项 3.点击Actions导出信任证书到桌面(expert root certificate to desktop) 4.在浏览器中添加对应的证…...
在线教育本地化分发:代理IP实现区域访问控制与内容适配
在在线教育本地化分发场景中,代理IP通过地理精准识别、动态内容适配与合规访问控制,成为突破区域限制、提升用户体验的核心技术工具。以下是基于2025年技术实践的解决方案: 一、区域访问控制的核心机制 地理IP库匹配与白名单策略 通过代理IP的…...
JAVA的常见API文档(上)
游戏打包 注意API文档中的方法不需要记忆!! 了解之后如果需要可以查询API文档 对Math的方法总结: 运用刚学的Math方法加快代码的运行效率 可以减少循环次数 找规律: 发现因子有规律: 必定一个大于平方根,…...
【数据结构】_二叉树
1.二叉树链式结构的实现 1.1 前置说明 在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树&#x…...
ALIENTEK精英STM32F103开发板 实验0测试程序详解
#include "sys.h" #include "usart.h" #include "delay.h" //ALIENTEK精英STM32F103开发板 实验0 //新建工程 实验 //技术支持:www.openedv.com //广州市星翼电子科技有限公司 int main(void) { u8 t0; //见注释1 St…...
LeetCode 33. 搜索旋转排序数组:二分查找的边界艺术
文章目录 问题描述解决思路代码实现关键点解析1. 为什么用 nums[left] < nums[mid]?2. 示例分析案例 1:数组 [3, 1],目标值 1案例 2:数组 [5],目标值 5 边界条件处理1. 单元素数组2. 完全有序数组3. 严格递增与重复…...
Rust 学习笔记:关于 HashMap 的练习题
Rust 学习笔记:关于 HashMap 的练习题 Rust 学习笔记:关于 HashMap 的练习题以下代码能否通过编译?若能,输出是?以下代码能否通过编译?若能,输出是? Rust 学习笔记:关于 …...
(头歌作业)—6.1 葡萄酒评论分析报告(project)
第1关:葡萄酒评论分析报告——国家列表和平均分 任务描述 本关任务:编写程序,多维度分析葡萄酒数据。 相关知识 葡萄酒评论分析报告描述 winemag-data.csv 文件 winemag-data.csv 包含 编号、国家、描述、评分、价格、省份 等 6列 和12974…...
下集:一条打包到底的静态部署之路
说完坑,再来讲正经操作。 这次我决定写得明明白白,清清楚楚,把那条“Spring Boot 扛着 Next.js 上线”的路子掰碎了揉细了告诉你。 无废话、无迷信、无AI幻觉。 第一步:Next.js 静态导出 项目根目录下的 next.config.js 要写得…...
多商户商城系统源码解析:开发直播电商APP的技术底层实战详解
随着直播电商的火爆,越来越多的创业者和企业都在寻求打造自己的多商户商城系统,以实现“人、货、场”三者的深度融合。然而,从一个简单的电商平台到一个功能完善的直播电商APP,其技术底层架构和实现过程并非一蹴而就。本文将从架构…...
每日Prompt:生成自拍照
提示词 帮我生成一张图片:图片风格为「人像摄影」,请你画一张及其平凡无奇的iPhone对镜自拍照,主角是穿着JK风格cos服的可爱女孩,在自己精心布置的可按风格的房间内的落地镜前用后置摄像头随手一拍的快照。照片开启了闪光灯&…...
LeetCode 热题 100_寻找重复数(100_287_中等_C++)(技巧)(暴力解法;哈希集合;二分查找)
LeetCode 热题 100_寻找重复数(100_287_中等_C) 题目描述:输入输出样例:题解:解题思路:思路一(暴力解法):思路二(哈希集合):思路三&am…...
多模态学习(三)—— ROPE位置编码:从理论到实践
ROPE位置编码:从理论到LLaMA的实践 一、前言 ROPE(Rotary Positional Embedding,旋转位置编码)是一种通过旋转矩阵将位置信息融入Token Embedding的编码方法。相比传统Transformer的绝对位置编码,ROPE能更灵活地建模…...
Redis——过期删除策略和内存
过期删除策略 Redis可以对key设置过期时间,因此需要有相应的机制将已过期的键值对删除 设置了过期时间的key会存放在过期字典中,可以用presist命令取消key过期时间 过期字典存储在redisDb结构中: typedef struct redisDb {dict *dict; …...
Selenium无法定位元素的几种解决方案详解
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 1、frame/iframe表单嵌套 WebDriver只能在一个页面上对元素识别与定位,对于frame/iframe表单内嵌的页面元素无法直接定位。 解决方法: …...
开源项目实战学习之YOLO11:12.3 ultralytics-models-sam-encoders.py源码分析
👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-encoders.pyblocks.py: 定义模型中的各…...
Bitmap原理及Hive去重方式对比
1. 什么是 Bitmap? Bitmap(位图)是一种用位(bit)来表示数据集合的数据结构。每个位代表一个元素是否存在,比如: 一个长度为N的bitmap,每一位对应一个元素的状态(0或1&a…...
力扣-比特位计数(统计一个数二进制下1的个数)
下面是题面 1.用c的内置函数__builtin_popcount() 语法:__builtin_popcount(int x),函数会返回一个二进制下x所含的1的个数 2.直接数位枚举 这是最慢也是暴力做法,写法也很简单 用一个while循环…...
开源项目实战学习之YOLO11:12.2 ultralytics-models-sam-decoders.py源码分析
👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-decoders.pyblocks.py: 定义模型中的各…...
Python训练营打卡Day28
浙大疏锦行 DAY 28 类的定义和方法 知识点回顾: 1.类的定义 2.pass占位语句 3.类的初始化方法 4.类的普通方法 5.类的继承:属性的继承、方法的继承 作业 题目1:定义圆(Circle)类 要求: 1.包含属性&#x…...
【前端基础】HTML元素隐藏的四个方法(display设置为none、visibikity设置为hidden、rgba设置颜色、opacity设置透明度)
HTML元素隐藏的四个方法 1、display设置为none 元素不显示出来。不占位置,也没有任何空间。就不存在一样。 2、visibility设置为hidden 默认:visible。元素可见设置为hidden:元素不可见,但是会占据这个元素应该占用的空间。 3、…...
STM32中的DMA
DMA介绍 什么是DMA? DMA(Direct Memory Access,直接存储器访问)提供在外设与内存、存储器和存储器之间的高速数据传输使用。它允许不同速度的硬件装置来沟通,而不需要依赖于CPU,在这个时间中,CPU对于内存…...
小型气象站应用之鱼塘养殖方案
概述 "看天吃饭",在农村经常听到这句话,鱼塘也不例外。天气的急剧变化,或连续的不利天气都有可能造成鱼类"浮头",甚至"翻肚子",更甚至"翻塘",一年白忙活了。 鱼塘…...
Makefile变量冲突与包含关系解析
Nuttx makefile每层独立,除非显示的通过include的方式包含。 Makefile调试技巧 打印变量 $(info CSRCS$(CSRCS))查看变量赋值过程 make --debugv在 Makefile 中,变量的作用域和可见性取决于 包含关系(include) 和 递归调用&…...
2025/517学习
对离群值怎么操作。这个就是拟合操作的。用更弯曲的曲线去拟合,如常见函数log 多元回归和单元回归 如题,如果我有多个自变量,来对一个因变量进行OLS回归,有没有operator可以做到?(ts_regression似乎只支持一个…...
浅谈前端架构设计与工程化
引言 在当今快速发展的Web开发领域,前端已经从简单的页面展示演变为复杂的应用程序开发。随着项目规模的扩大和团队协作的需求增加,良好的前端架构设计和工程化实践变得至关重要。本文将探讨如何构建可维护、可扩展的前端架构,并介绍现代前端…...
JMeter 教程:编写 POST 请求脚本访问百度
目录 ✅ 教程目的 🛠️ 环境要求 📄 实操步骤 第一步:启动 JMeter 第二步:添加测试计划和线程组 1.右键左侧 Test Plan(测试计划) 2.选择 Add → Threads (Users) → Thread Group(线程组…...
Typescript学习教程,从入门到精通,TypeScript 函数语法知识点及案例代码(5)
TypeScript 函数语法知识点及案例代码 TypeScript 提供了丰富的函数语法特性,使得函数定义更加灵活和强大。以下将详细介绍 TypeScript 中函数的相关语法,包括函数定义、可选参数、默认参数、剩余参数、重载函数、递归函数、匿名函数、箭头函数以及回调…...
【51单片机定时器/计数器】
目录 简介 定时器配置流程 1.配置定时器工作方式寄存器TMOD 2.配置中断寄存器TCON 3.定时时间计算公式 4.配置中断允许寄存器IE 5.使用中断函数完成中断 简介 定时器/计数器本质都是对脉冲信号进行计数,区别在于作为定时器时的脉冲信号来自于晶振12分频&…...
Oracle 的 ASSM 表空间
Oracle 的 ASSM(Automatic Segment Space Management)表空间 是一种自动管理段空间的技术,通过位图(Bitmap)机制跟踪数据块的使用情况,替代传统的手动管理(MSSM,即 Freelist 管理&am…...
C++学习:六个月从基础到就业——C++11/14:auto类型推导
C学习:六个月从基础到就业——C11/14:auto类型推导 本文是我C学习之旅系列的第四十一篇技术文章,也是第三阶段"现代C特性"的第三篇,主要介绍C11/14中的auto类型推导机制。查看完整系列目录了解更多内容。 引言 在现代C…...
select语句的书写顺序
一.MySQL SELECT语句的执行顺序 MySQL中SELECT语句的执行顺序与SQL语句的书写顺序不同,理解这个执行顺序对于编写高效查询非常重要。 1.标准SELECT语句的执行顺序 FROM子句(包括JOIN操作) 首先确定数据来源表执行表连接操作 WHERE子句 对F…...
OpenWebUI新突破,MCPO框架解锁MCP工具新玩法
大家好,Open WebUI 迎来重要更新,现已正式支持 MCP 工具服务器,但 MCP 工具服务器需由兼容 OpenAPI 的代理作为前端。mcpo 是一款实用代理,经测试,它能让开发者使用 MCP 服务器命令和标准 OpenAPI 服务器工具ÿ…...
【Day28】
总结: Python 通过缩进来定义代码块的结构。当解释器遇到像 def, class, if, for 这样的语句,并且后面跟着冒号 : 时,它就期望接下来会有一个或多个缩进的语句来构成这个代码块。如果它没有找到任何缩进的语句(即代码块是空的&am…...
STM32 | FreeRTOS 消息队列
01 一、概述 队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息,当队列中的消…...
Vue-事件修饰符
事件修饰符 prevent (阻止默认事件) 超链接 点击事件 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>事件修饰符</title><!-- 引入Vue --><script …...
c++函数调用运算符及类型转换运算符重载
author: hjjdebug date: 2025年 05月 17日 星期六 14:44:48 CST descrip: c函数调用运算符及类型转换运算符重载 文章目录 0. 前言. 运算符包括以下运算符.1. 运算符重载语句一般格式:2. 函数调用运算符:3. 类型转换运算符: 例如 int(); double(); bool(…...
如何在 Windows 10 或 11 中安装 PowerShellGet 模块?
PowerShell 是微软在其 Windows 操作系统上提供的强大脚本语言,可用于通过命令行界面自动化各种任务,适用于 Windows 桌面或服务器环境。而 PowerShellGet 是 PowerShell 中的一个模块,提供了用于从各种来源发现、安装、更新和发布模块的 cmdlet。 本文将介绍如何在 PowerS…...
84.评论日记
原链接 这个视频我发了四五条评论。评论内容甚至和下面这个视频内的其他评论一样。 找了另外的账号也发了。 发现,无论是我这个账号,还是其他的账号,评论都无法看到。 我大胆猜测有一种机制,某些官号会被设置成一种高检测的等…...
一周学会Pandas2 Python数据处理与分析-Pandas2数据添加修改删除操作
锋哥原创的Pandas2 Python数据处理与分析 视频教程: 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 对数据的修改、增加和删除在数据整理过程中时常发生。修改的情况一般是修改错误,还有一种情况是格式转换…...
荷兰国旗问题 之 指针划分区间问题
文章目录 首先介绍一下什么是荷兰国旗问题?问题描述为:给定一个由红色、白色和蓝色三种颜色组成的无序数组,将数组元素按颜色排序,使得所有红色元素在前,白色元素居中,蓝色元素在后。这里的 “颜色” 通常用…...
冒泡排序-java
public class BubbleSort{ public static void bubbleSort(int[] arr) { int n arr.length; boolean swapped; // 外层循环控制遍历的轮数 for (int i 0; i < n - 1; i) { swapped false; for (int j 0; …...
进阶-数据结构部分:2、常用排序算法
飞书文档https://x509p6c8to.feishu.cn/wiki/FfpIwIPtviMMb4kAn3Sc40ABnUh 常用排序算法 这几种算法都是常见的排序算法,它们的优劣和适用场景如下: 冒泡排序(Bubble Sort):简单易懂,时间复杂度较高&…...
人工智能-自然语言与语音产品实现
一、语义相似度 (一)、文本向量化 1、文本向量化(Text Vectorization) 是自然语言处理(NLP)中的核心预处理步骤,旨在将人类语言的文本转换为计算机可处理的数值向量(数学表达&…...
阿里巴巴开源移动端多模态LLM工具——MNN
MNN 是一个高效且轻量级的深度学习框架。它支持深度学习模型的推理和训练,并在设备端的推理和训练方面具有行业领先的性能。目前,MNN 已集成到阿里巴巴集团的 30 多个应用中,如淘宝、天猫、优酷、钉钉、闲鱼等,覆盖了直播、短视频…...
SpringBootAdmin:全方位监控与管理SpringBoot应用
监控的意义 1. 监控服务状态是否宕机 2. 监控服务运行指标 (内存,虚拟机,线程,请求等) 3. 监控日志 4. 管理服务 (服务下线) 可视化监控平台 Spring Boot Admin, 开源社区项目, 用于管理和监控SpringBoot应用程序. 客户端注册到服务端, 通过HTTP请求方式, 服务端定期从客…...