springboot 项目托管 vue 项目
一. 操作流程
整体流程如下
- vue 项目打包
- springboot 托管静态文件
- 处理路由跳转问题
1. vue 项目打包
我的版本是 vue3 项目,使用了 vite,可以直接使用 vite build
命令将 vue 代码打包为独立的文件。(如果不是用 vite 也可以自己查一下如何打包)
打包后会在 dist
目录生成如下目录结构的文件(注意:那个 css 和 js 文件名每次都不一样)
这些文件以 index.html
为入口,会以相对路径调用 assets 路径下的 css 文件、js 文件以及静态资源。
2. springboot 托管静态文件
这些打包好的文件,进行静态资源托管后即可正常使用。你可以使用 nginx 来托管这些静态文件。
然而这次我们想使用 springboot 直接托管这些静态文件。
引入 spring-boot-starter-web 依赖,这时不需要额外的配置,只要放在 src/main/resources/static
文件夹下的文件,都可以被正确访问到。
例如,在 src/main/resources/static
中放一个 index.html
文件,地址 127.0.0.1:8080/index.html
就可以直接访问到 index.html
文件。
所以把 vue 打包好的文件放在 src/main/resources/static
目录下即可
3. 处理路由跳转问题
但在实际使用时,会发现有这样一个问题,就是前端代码会设置前端的路由跳转,例如从根路径跳转到一个业务路径(/
=> /other_route
)。
如果不离开这个页面还好,但是如果在其他路径刷新页面,或者浏览器直接输入其他路径访问,就会发现 404 无法访问的问题,那么这个问题如何解决呢?
在 springboot 代码中添加如下 Controller 即可解决这个问题(注意要列出所有需要支持的前端路由)
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class RouterController {
@GetMapping({"/", "/home", "/about", "/user/**"}) // <=== 列出所有需要支持的前端路由
public String forward() {
return "forward:/index.html";
}
}
二、原理详解
当浏览器访问路径 /some_path
的时候,依次发生如下事件:
- 浏览器访问 SpringBoot Controller,路径是
/some_path
- SpringBoot 在后端服务内,将请求转发给了
index.html
(这里的核心是浏览器的地址不变,也没有跳转) - SpringBoot 服务器返回给前端 200 状态码,以及
index.html
的内容 - 浏览器执行
index.html
中的 javascript 脚本(Vue 代码) - 脚本检测当前页面路径是
/some_path
,执行了正确的路由操作
其他:return "index.html"
和 return "forward:/index.html"
的行为差异
return "index.html"
- 这会触发重定向(redirect)
- 浏览器会收到 302/303 状态码
- 浏览器会重新请求 index.html
- URL 会变成 /index.html
- Vue Router 读取到的是 /index.html
return "forward:/index.html"
- 这是服务器内部转发
- 浏览器只收到一个响应
- url 保持不变,仍然是原始 url
- Vue Router 能正确读取到原始 url