将 Vue 前端和 Spring Boot 后端部署在同一台服务器上是常见且高效的部署方式。通常的做法是:使用 Spring Boot 作为后端服务处理 API 请求,同时托管编译后的 Vue 前端静态资源(HTML、JS、CSS 等)。以下是详细实现步骤:
🧩 一、项目结构规划
假设你的服务器上运行一个 Java 应用(Spring Boot),你希望它同时提供前端页面。
your-spring-boot-project/
├── src/
│ └── main/
│ ├── java/ # 后端代码
│ ├── resources/
│ │ ├── static/ # Vue 打包后的文件放在这里
│ │ │ ├── css/
│ │ │ ├── js/
│ │ │ └── index.html
│ │ └── application.yml
│ └── resources/static/ # 或者直接放这里也行
└── pom.xml
✅ 步骤 1:构建 Vue 项目(生成静态文件)
在本地开发完成后,执行打包命令:
npm run build
# 或 yarn build
这会在 dist/ 目录下生成生产环境的静态文件,例如:
dist/
├── index.html
├── assets/css/app.xxxx.css
├── assets/js/app.xxxx.js
✅ 步骤 2:将 Vue 静态文件复制到 Spring Boot 的 static 目录
将 dist 文件夹下的所有内容复制到 Spring Boot 项目的 src/main/resources/static/ 目录中。
⚠️ 注意:不要复制整个
dist文件夹,而是复制其内部的内容。
例如:
cp -r dist/* your-spring-boot-project/src/main/resources/static/
这样访问根路径 / 时,Spring Boot 就会自动返回 index.html。
✅ 步骤 3:配置 Spring Boot 支持单页应用(SPA)路由
Vue Router 使用 history 模式时,刷新页面会出现 404 错误,因为后端没有对应路径的接口。
解决方法:添加一个兜底路由,将所有未知请求都转发到 index.html。
方法一:使用 @Controller 返回 index.html
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SpaController {
@GetMapping(value = {"/", "/login", "/dashboard", "/user/**", "/api-docs/**"}) // 添加你需要支持的前端路由
public String index() {
return "index.html"; // 返回 static 目录下的 index.html
}
}
💡 注意:这个方法只适用于非 API 路由。确保你的 API 是以
/api开头,避免冲突。
方法二:使用 WebMvcConfigurer(推荐)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(3600)
.resourceChain(true);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{spring:\w+}")
.setViewName("forward:/index.html");
registry.addViewController("/**/{spring:\w+}")
.setViewName("forward:/index.html");
registry.addViewController("/{spring:\w+}/**{spring:?!(\.js|\.css|\.png|\.jpg|\.gif|\.ico|\.svg)$}")
.setViewName("forward:/index.html");
}
}
或者更简单粗暴的方式(适合 history 模式):
@Bean
public ViewResolver viewResolver() {
return new InternalResourceViewResolver() {{
setPrefix("/static/");
setSuffix(".html");
}};
}
// 兜底路由
@GetMapping("/{path:[^\.]*}")
public String redirectApi() {
return "forward:/";
}
✅ 步骤 4:确保 API 和静态资源路径不冲突
建议将所有后端 API 接口统一加上前缀,如 /api/**,避免与前端路由混淆。
@RestController
@RequestMapping("/api/user")
public class UserController {
// ...
}
✅ 步骤 5:打包并部署到服务器
打包 Spring Boot 应用
mvn clean package
生成 target/your-app.jar
上传到服务器并运行
scp target/your-app.jar user@your-server:/opt/app/
ssh user@your-server
# 运行
nohup java -jar your-app.jar > app.log 2>&1 &
或使用 systemd 守护进程管理。
✅ 步骤 6:(可选)使用 Nginx 反向(推荐用于生产)
虽然可以直接通过 Spring Boot 提供前端,但更推荐使用 Nginx 来托管静态资源,提高性能和安全性。
Nginx 配置示例:
server {
listen 80;
server_name your-domain.com;
# 托管 Vue 静态文件
location / {
root /var/www/vue-app;
try_files $uri $uri/ /index.html;
}
# 将 API 请求到 Spring Boot
location /api/ {
proxy_pass http://localhost:8080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
此时 Spring Boot 只负责提供 API,不托管前端文件。
🔁 总结:两种主流方案对比
| 方案 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| Spring Boot 托管前端 | 把 Vue 打包文件放入 static,由 Spring Boot 返回 |
简单,一键部署 | 静态资源性能较差,占用 Java 内存 |
| Nginx 托管前端 + Spring Boot 提供 API | Nginx 处理静态资源,反向 API 到 Spring Boot | 高性能、安全、可扩展 | 部署稍复杂 |
✅ 推荐生产环境使用 Nginx + Spring Boot 分离部署。
🛠️ 补充建议
- 使用 CI/CD 自动化构建部署流程(如 Jenkins、GitHub Actions)
- 配置 HTTPS(Let’s Encrypt)
- 设置 CORS(开发阶段),生产建议同源部署避免跨域
如有需要,我可以提供完整的项目结构示例或自动化脚本。欢迎继续提问!
CLOUD技术笔记