这不是一篇教你"怎么写代码"的文章,而是一篇帮你"想清楚再动手"的技术决策参考。如果你正在纠结"我的项目到底要不要前后端分离",或者"分离之后权限怎么搞",这篇文章就是为你写的。
一、为什么你会在"折不折腾"之间反复横跳?
过去十年,前后端分离成了Web开发的政治正确。你去面试,说项目用的还是Thymeleaf/JSP,面试官可能眉头一皱;你说用的Vue+Spring Boot,对方频频点头。但真相是:技术选型不看规模、不看场景,就是耍流氓。
我见过3个人的创业团队,硬上微服务+前后端分离,结果半年没上线;也见过大厂内部的后台系统,老老实实用传统MVC,一年迭代几十个版本稳如老狗。
所以,先别急着抄作业,搞清楚自己的处境。
二、三种主流方案,一张表看懂
| 方案 | 技术栈 | 适用场景 | 开发效率 | 学习成本 | 接口复用能力 |
|---|---|---|---|---|---|
| 传统MVC | Spring Boot + Thymeleaf + HTMX | 小团队、后台管理、官网 | ⭐⭐⭐⭐⭐ | ⭐ | ⭐ |
| 混合渲染 | Spring Boot + Thymeleaf + CDN Vue | 需要接口复用、不想上前端工程化 | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 完全分离 | Spring Boot + Vite + Vue/React | 中大型团队、多端复用、复杂交互 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
接下来逐一拆解。
三、方案一:传统MVC + HTMX("不折腾"的极致)
✅HTMX是什么?
HTMX是一个轻量级库,让你直接用HTML属性发AJAX请求,后端返回HTML片段,它自动替换到页面上。不需要写一行JavaScript。
html
<!-- 这就是全部代码,不需要写JS -->
<button hx-get="/api/users" hx-target="#user-list">
加载用户列表
</button>
<div id="user-list"></div>
✅谁适合用?
-
你一个人全栈,或者团队≤5人
-
项目是后台管理系统、企业官网、内部工具
-
前端交互很简单(表单提交、列表翻页、弹窗)
-
没有移动端APP需要复用接口
-
你不想学NPM/Vite/Webpack,就想写Java
✅谁不适合?
-
有APP需要调用同一套API
-
交互复杂(如拖拽、实时协作、富文本编辑)
-
需要前后端并行开发解耦排期
一句话总结:如果你的核心诉求是"快速出活",选它。HTMX让你用20年前的方式写Web,但体验接近SPA,而且Spring Boot天然支持返回HTML片段,开箱即用。
四、方案二:混合渲染("既要又要"的务实派)
✅核心思路:后端渲染页面骨架,前端用CDN引入Vue填充动态数据。
html
<!-- Thymeleaf渲染页面结构 -->
<div id="app">
<ul>
<li v-for="user in userList">{{ user.name }}</li>
</ul>
</div>
<!-- CDN引入Vue,完全不用NPM -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: { userList: [] },
mounted() {
fetch('/api/users')
.then(res => res.json())
.then(data => this.userList = data);
}
});
</script>
✅谁适合用?
-
有APP需要和Web端复用同一套JSON接口
-
但前端团队只有1-2人,不想搞Vite工程化
-
交互复杂度中等(列表渲染、表单校验、弹窗)
-
需要SEO(页面由Thymeleaf渲染,搜索引擎能抓到内容)
✅技术要点:
-
权限控制 :后端在DTO里带上权限标志位(
canEdit/canDelete),前端用v-if控制按钮显隐 -
状态管理 :MPA模式下,页面跳转会刷新,直接用
localStorage存登录态和权限码,不需要Pinia/Vuex -
开发启动:后端Maven启动即可,前端没有任何独立进程
一句话总结:这是"既享受前后端接口分离的好处,又逃避前端工程化复杂度"的最优解。适合中小团队,非常务实。
五、方案三:完全分离("正规军"打法)
✅技术栈:Spring Boot(后端)+ Vite(前端构建工具)+ Vue/React
这才是大家通常说的"前后端分离项目"。前后端代码仓库分开(或同一仓库不同目录),各跑各的服务,通过API通信。
✅开发时的启动方式:
-
后端:IDEA跑Spring Boot主类,或
mvn spring-boot:run,默认8080端口 -
前端:
npm run dev,Vite起开发服务器,默认5173端口 -
联调:配置Vite代理,把
/api请求转发到8080,解决跨域问题
✅部署时的构建流程:
-
前端:
npm run build→ 产出dist目录 -
后端:使用
frontend-maven-plugin自动下载Node、执行构建、把dist复制到src/main/resources/static -
最终:
mvn clean package打出一个包含前后端的可执行Jar包
✅关于Node版本管理:
Maven的frontend-maven-plugin需要指定nodeVersion,默认会强制下载该版本。如果想用本机已装的Node,配置useGlobalNode: true,但版本号必须完全一致(字符串匹配),不支持"高于即可"。
✅权限控制(这是最大的坑):
-
页面级权限:在路由守卫(Vue-Router)中拦截,根据权限码动态添加路由
-
按钮级权限 :后端返回权限码列表,前端存Pinia,封装
v-permission自定义指令控制显隐 -
行内按钮权限 (最复杂):后端在组装列表DTO时,把
canEdit/canDelete等标志位算好直接传给前端,前端只做展示判断,绝不自己写业务逻辑判断
✅谁适合用?
-
前端团队≥5人,后端团队≥5人
-
需要并行开发、独立部署
-
交互复杂(如在线文档、数据大屏、实时看板)
-
有APP/小程序等多端复用API需求
✅谁不适合?
-
小团队
-
项目周期紧
-
核心需求只是"把数据展示出来"
六、一个容易被忽视的问题:MPA vs SPA的状态管理
✅多页应用(MPA):每次页面跳转都刷新,JavaScript上下文被销毁重建,所以:
-
状态存
localStorage足够 -
不需要Pinia/Vuex(数据活不过页面刷新)
-
退出登录时记得清
localStorage
✅单页应用(SPA):页面不刷新,JS上下文持续存在,所以:
-
Pinia管理"页面运行时"状态(当前Tab、表单暂存、购物车)
-
localStorage只负责持久化(登录态、权限码) -
两者配合使用,各司其职
七、终极决策树:你的项目到底选哪个?

八、最后说几句掏心窝的话
前后端分离不是银弹。 它解决的是"团队协作"和"多端复用"的问题,但也引入了"环境不一致"、"跨域调试"、"构建流水线"、"权限双重控制"等一系列新麻烦。
用不用前后端分离,看的不是技术潮不潮流,看的是你的团队规模、业务复杂度、交付周期。 一个人全栈用HTMX,两周交付一个后台,比花一个月搭微服务分离架构,然后在各种配置里焦头烂额,要明智得多。
技术选型是田忌赛马,不是奥运会。 用最合适的工具,打你能打赢的仗。
如果你读到这里,恭喜你,至少省了一个月调研时间。如果还有具体场景拿不准,欢迎带着你的项目情况来找我聊。