跳到主内容

Spring Boot + Vue3 环境总搭不起来?我按这6类报错逐个拆掉

去年帮同事搭一套 Spring Boot + Vue3 的管理后台,环境折腾了整整一天半,其中大半时间不是花在写代码上,是花在猜报错上。后来我把这些报错按"从外到内"排了序,再遇到同类问题基本十分钟定位。这篇把这个排查路径完整写出来。

先说明边界:站内已经有一篇跟着现成电商脚手架走的Spring Boot + Vue3 开发环境搭建长文,那篇适合你要跑通某个具体开源项目。这篇不针对任何具体项目,讲的是自己从零起项目时的通用坑位——大部分人实际遇到的是这一类。

典型症状:四种报错长得完全不像同一个问题

第一类是浏览器控制台红一片,写着 Access to XMLHttpRequest ... has been blocked by CORS policy。前端 5173,后端 8080,请求被同源策略拦了。

第二类是接口通了但数据不对。后端返回 2024-05-20T10:30:00 这种带 T 的 ISO 串,前端日期组件要的是 2024-05-20 10:30:00,表格里显示成一坨难看的字符串,按时间排序还错。

第三类最有迷惑性:Cross origin requests are only supported for protocol schemes: http...。这个跟跨域配置一点关系都没有,纯粹是因为你双击打开了打包后的 index.html,走的是 file:// 协议。

第四类只在生产环境出现。开发时上传图片一切正常,部署到服务器之后图片全裂。原因是文件被写进了 jar 包内部,或者根本没有配置外部目录的 URL 映射。

排查路径:从外到内,别一上来就改后端

我的顺序是固定的,命中率比乱试高很多。

先看请求到底发出去没有

打开 F12 切 Network,找一个登录接口或者列表接口,看三件事:请求 URL 是不是你以为的那个、有没有被代理转发、返回体是不是 JSON。

如果返回 401、404、500,按顺序查:后端控制台有没有异常堆栈、接口路径对不对、请求有没有走到代理。这一步能解决掉一大半"我明明写了接口"的问题。

再看浏览器看到的地址是不是同源

这是跨域问题的核心判断。前端跑在 5173、后端跑在 8080,浏览器就会拦。但注意——如果请求是被 Vite 代理转发的,浏览器看到的依然是同源,根本不会触发拦截。

所以看到 CORS 报错的第一步不是去后端加注解,而是确认你的代理到底生效了没有。改完 vite.config.js 一定要重启 dev server,这个配置不热更新。我在这里浪费过至少半小时。

最后才动后端和打包配置

前面都排除了,再考虑后端 CORS 配置、Jackson 日期格式、静态资源映射、Maven 打包参数。

根因定位:四个坑各自的真实原因

跨域的根子是前后端端口不同,不是后端不让你访问。所以解决方案有三条,优先级很明确。

日期格式的根子是 Jackson 默认序列化成了 ISO-8601,前端组件未必认这套。

file:// 那条报错的根子最朴素——浏览器不允许跨协议请求,你必须用 http://localhost 访问。起一个 dev server 或者挂个 Nginx 就行,双击文件这条路从来就没通。

图片裂的根子是 Spring Boot 默认静态目录是 classpath:/static,而上传目录在 jar 外面。上传文件不能存进 jar 包里,必须配外部路径映射。而且这个坑只在生产暴露,开发环境几乎发现不了。

修复动作:可用的配置长这样

开发环境跨域,我推荐前端代理方案,理由是它的转发思路跟生产环境的 Nginx 反代天然一致:本地配 /api 到 8080,生产配 /api 到后端端口,一套思维用到底,不用来回切换。

// vite.config.js
server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true
    }
  }
}

changeOrigin 一定要设成 true。不设的话后端拿到的是前端的 Host 头,某些框架对 Host 头有校验(Spring Security 在特定配置下会直接拒绝请求),这个坑见过不止一次。

如果前端没法改代理(比如别人在局域网直接访问你的前端地址),就在后端加 CORS:实现 WebMvcConfigurer 重写 addCorsMappings,或者给少量接口加 @CrossOrigin 注解。第三种"浏览器关跨域校验"只适合临时调试,别用在正经项目上。

日期格式统一放在后端做,改 application.yml:

spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

时区也别漏,缺了 GMT+8 会出现差八小时的经典问题。

上传目录映射要配两处:一处是 spring.resources.static-locations 加上外部磁盘路径(比如 file:D:/upload/),另一处是在配置类里注册 WebMvcConfigurer,把 /upload/** 映射到那个目录。少配任何一处,图片都是裂的。

打包就一条命令:mvn clean package -DskipTests,跑完在 target 目录拿 jar。依赖版本、JDK 版本要求这些,以你所选版本的官方文档为准,不同大版本之间差异不小,别照抄旧教程。

怎么防止再犯:搭环境时的三条纪律

第一,前后端先各跑各的,再联调。后端先确认接口用 curl 或 ApiPost 能通,前端先确认页面能起来,两边都单跑没问题再对接。一起启动一起报错,你根本分不清锅在谁。

第二,改配置必重启。vite.config.js、application.yml 这类都不是热更新友好的,改完不重启是最常见的假故障来源。

第三,写一份自己的环境清单。JDK 版本、Node 版本、后端端口、前端端口、代理前缀、上传目录,全记在一个 md 里。这个习惯我在别的场景也吃到了甜头——做桌面端采集程序的时候,把字段映射、限流阈值、重试策略都写清楚,后面接手的人不用猜(类似的写法可以参考小红书采集从关键词筛选到批量导出的完整实操)。

还有一点容易忽略:部署环境跟开发环境不是一回事。我在做 OCR 类项目时就遇到过客户要求数据不得离境、网络环境受限的情况(见发票识别从踩坑到自动化的复盘),这类约束要在搭环境之前问清楚,否则做到一半发现不能用离线依赖,返工成本很高。

常见问题

Q:配了代理怎么还是跨域报错?

A:先确认 dev server 重启了没有,这是最高频的原因。再看你的请求 URL 是不是真的以 /api 开头——代理是按前缀匹配的,请求写成完整后端地址的话压根不会走代理。

Q:为什么开发时图片正常,一打包就 404?

A:因为上传的文件写到了 jar 包内部或者临时目录。配一个外部磁盘路径,同时在配置类里注册 URL 映射,两处都要有。

Q:生产环境还需要后端开 CORS 吗?

A:如果用 Nginx 反代把前后端统一到同一个域名下,就不需要,前端代码里也不用做任何跨域处理。这也是我推荐开发期就走代理的原因,跟生产保持一致。

Q:日期改了配置还是带 T?

A:检查是不是某个字段上单独加了 @JsonFormat,字段级注解会覆盖全局配置。另外确认这个接口返回的是不是 String 而非 Date 类型。

Q:有没有必要一上来就用现成脚手架?

A:取决于目的。要学架构就看成熟项目的源码,要交付自己的东西就从零起项目,依赖越少越好排错。两个目的混在一起最容易卡住——你会发现自己既没读懂源码,也没跑通自己的东西。

相关阅读

分享到:

本文链接:https://www.biyeyuanma.cn/post/255.html

服务热线

加我微信

加我微信