Vue3 + SpringBoot 前后端联调实践:从跨域到JWT完整流程

本文基于个人项目 VibeHub 创意管理系统,系统性总结 Vue3 + SpringBoot 前后端分离开发中的完整工程实践,包括:

  • 跨域机制(Vite Proxy + CORS)
  • JWT 登录认证体系
  • Axios 工程化封装
  • 统一数据返回结构设计
  • 前后端接口协作规范
  • 常见联调问题排查

一、项目背景(真实工程场景)

在开发 VibeHub 创意管理系统时,我尝试从“课程级项目”升级到“工程化前后端分离系统”。

在数字化转型与敏捷开发的双重驱动下,前后端分离已成为现代 Web 应用开发的事实标准。通过将用户界面与核心业务逻辑解耦,开发团队能够实现技术栈的独立演进、团队的高效协同以及系统的高弹性伸缩。

以 VibeHub 创意管理系统为例,该项目作为典型的数字化资产与创意协作平台,其核心业务涵盖多模态创意资产管理、AI 辅助设计 Prompt 提示词上下文追溯以及敏捷工作流协同。为了保障高频人机交互的流畅性与后端高并发数据处理的稳定性,VibeHub 采用了现代化的技术选型:前端基于 Vue 3 + Vite 构建响应式、富交互的用户界面;后端采用 Spring Boot 3 + Spring Security 6 搭建高性能、无状态的 RESTful API 引擎。

前后端分离架构在释放开发灵活性的同时,也引入了诸如跨域资源限制、多层安全认证对接、状态同步以及异构系统间数据契约规范等技术挑战。本篇将以 VibeHub 系统的工程实践为蓝本,系统性阐述 Vue 3 与 Spring Boot 3 从零到一的联调流程与核心架构设计,为全栈开发与系统集成提供深度的落地指南。

跨域资源共享的底层机制与开发期代理配置同源策略(Same-Origin Policy)是浏览器最核心也最基本的安全功能。在进行本地联调时,由于前端服务通常托管在 http://localhost:5173(Vite 默认端口),而后端服务则运行在 http://localhost:8080(Tomcat 默认端口),两者的端口不同,从而构成了跨域请求。 跨域的识别由源(Origin)的三元组决定:

Origin =

当且仅当 Protocol(协议)、Host(主机名)和 Port(端口)完全一致时,浏览器才允许数据在双端自由流动,否则任何非同源的 AJAX/Fetch 请求都会被浏览器默认拦截。为了在开发阶段绕过这一物理限制,Vite 提供了内置的开发服务器代理(Dev Server Proxy)机制。

整体架构如下:

技术栈

前端:

  • Vue3(Composition API)
  • Vite
  • Vue Router
  • Pinia
  • Axios
  • Element Plus

后端:

  • SpringBoot 3
  • Spring Security 6
  • JWT
  • MySQL
  • MyBatis / JPA

系统功能模块

  • 用户登录 / 注册
  • 创意内容发布
  • 分类管理
  • 评论系统
  • 个人中心
  • 后台管理(基础)

❗开发中的真实问题

在前后端联调过程中,主要遇到以下工程问题:

  • 跨域请求被浏览器拦截
  • 登录后 token 丢失或无效
  • 前后端数据结构不统一
  • Axios 请求散落难维护
  • Spring Security 导致接口 401/403
  • OPTIONS 预检请求失败

二、前后端分离的本质理解

在实际开发后我逐渐意识到:

前后端分离的核心不是“Vue + SpringBoot”,而是三件事:

✔ 1. 请求如何跨域通信

✔ 2. 身份如何在无状态下保持

✔ 3. 数据结构如何统一契约化


三、跨域问题完整解决方案

3.1 开发环境:Vite Proxy 代理机制

server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\/api/, '')
    }
  }
}

🧠 原理理解(非常重要)

Vite 代理的本质:

浏览器 → Vite(Node服务) → SpringBoot

这样绕开了浏览器同源策略限制。


✔ 优点

  • 无需后端处理跨域
  • 前端代码无需修改
  • 适合开发环境

3.2 生产环境:SpringBoot CORS 配置

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration config = new CorsConfiguration();

    config.setAllowedOrigins(List.of("http://localhost:5173"));
    config.setAllowedMethods(List.of("GET","POST","PUT","DELETE","OPTIONS"));
    config.setAllowedHeaders(List.of("*"));
    config.setAllowCredentials(true);
    config.setMaxAge(3600L);

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);

    return source;
}

⚠️ 跨域核心坑点

如果出现:

❌ Access-Control-Allow-Origin missing

通常原因是:

  • Spring Security 拦截了 OPTIONS 请求
  • CORS 没有优先加载

四、Axios 工程化封装(核心能力体现)

4.1 基础封装

import axios from 'axios'

const request = axios.create({
  baseURL: import.meta.env.DEV ? '/api' : import.meta.env.VITE_APP_API_URL,
  timeout: 15000
})

export default request

4.2 为什么必须封装 Axios?

如果不封装,会出现:

  • 请求分散
  • token 到处写
  • 错误处理混乱
  • 后期维护困难

五、JWT 登录认证体系(核心重点)

5.1 登录完整流程

前端登录请求
   ↓
后端验证账号密码
   ↓
生成 JWT Token
   ↓
返回前端
   ↓
前端存储 Token
   ↓
后续请求携带 Token
   ↓
后端解析 Token 放行

5.2 前端请求拦截器

request.interceptors.request.use((config) => {
  const token = localStorage.getItem('token')

  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }

  return config
})

5.3 后端 JWT 解析逻辑

Claims claims = Jwts.parser()
    .setSigningKey(secretKey)
    .build()
    .parseClaimsJws(token)
    .getBody();

String username = claims.getSubject();

✔ JWT 本质理解

JWT 的核心特点:

  • 无状态认证
  • 不依赖 Session
  • 客户端保存身份
  • 后端只做解析

六、统一数据返回结构设计(非常关键)

6.1 为什么必须统一?

如果不统一:

  • 前端需要写大量 if 判断
  • 接口风格混乱
  • 错误处理无法标准化

6.2 标准结构

public class StandardResponse<T> {
    private boolean success;
    private int statusCode;
    private String message;
    private T data;
}

6.3 返回示例

{
  "success": true,
  "statusCode": 200,
  "message": "success",
  "data": {
    "token": "xxx"
  }
}

七、Axios 响应拦截器(工程化关键)

request.interceptors.response.use(
  (res) => {
    const data = res.data

    if (data.success) {
      return data.data
    }

    return Promise.reject(data.message)
  },
  (error) => {
    if (error.response?.status === 401) {
      alert("登录已过期,请重新登录")
      window.location.href = "/login"
    }

    if (error.response?.status === 403) {
      alert("权限不足")
    }

    return Promise.reject(error)
  }
)

八、Spring Security + JWT 联动(进阶点)

8.1 Filter 拦截机制

SpringBoot 中通过 Filter 拦截每个请求:

请求 → Filter → SecurityContext → Controller

8.2 JWT Filter 核心逻辑

if (authHeader != null && authHeader.startsWith("Bearer ")) {

    String token = authHeader.substring(7);

    Claims claims = Jwts.parser()
        .setSigningKey(secretKey)
        .build()
        .parseClaimsJws(token)
        .getBody();

    String username = claims.getSubject();
}

九、真实踩坑总结(非常重要)

❌ 1. OPTIONS 请求失败

原因:

  • Spring Security 拦截预检请求

解决:

  • 放行 OPTIONS

❌ 2. token 明明存在却 401

原因:

  • Authorization 格式错误
  • 少了 Bearer

❌ 3. CORS 报错

原因:

  • allowCredentials + *

必须改为:

  • 明确 origin

❌ 4. 接口返回混乱

原因:

  • 没有统一 Response 结构

十、项目总结

通过 VibeHub 项目,我逐渐理解前后端分离的本质:

不是“Vue + SpringBoot 的组合”,而是一套完整的工程协作体系。
系统性地剖析了 Vue 3(Vite + Axios)与 Spring Boot 3(Spring Security 6 + JWT)从零到一的集成联调技术路径。通过在开发阶段巧妙利用前端 Node 本地代理转发规避浏览器的物理域界限,并在生产环境下将 CORS 过滤器上提至安全链顶端,开发团队既能够保留极度敏捷的日常迭代体验,又能够建立符合企业级纵深防御规范的安全防御线。

以 VibeHub 创意管理系统为代表的工程应用表明,建立在严密 StandardResponse 协议和全局异常捕获切面之上的联调机制,能够让双端的通信处于极度可控、可预测的轨道中,极大地改善了跨端协作的效率。

展望未来,随着以“意图导向、AI 智能体直接执行(Vibe Coding / Vibe Design)”为特征的 AI 原生开发范式不断走向成熟,前后端交互的技术表现形式虽然可能会发生质的飞跃,但双端之间关于网络同源性校验、无状态状态机生命周期管理以及一致性数据契约的底层架构规律依然坚固如初。熟练并系统性地掌握本文所总结的一整套联调与故障排除方法,是任何软件开发工程师构建安全、健壮、可伸缩的现代企业级 Web 架构的重要基石。
核心包括:

  • ✔ 数据契约(Response)
  • ✔ 身份体系(JWT)
  • ✔ 通信机制(CORS + Proxy)
  • ✔ 请求规范(Axios封装)

posted @ 2026-07-05 23:51  VincenzoHolmes  阅读(23)  评论(0)    收藏  举报