Spring Boot + Vue 应用部署策略详解

        🚀记录一下springboot vue的打包方式,第一种比较常用。

        在采用 Spring Boot + Vue 技术栈进行开发时,前后端分离的架构是主流选择。这种架构在部署上有多种策略,每种策略都有其适用场景。以下是几种核心的部署方式,从简单到复杂,供您参考。


1️⃣ 策略一:前后端分离部署

        这是最灵活、最常用的生产环境部署模式。前端和后端作为两个独立的服务,分别进行打包和部署。

⚙️ 后端部署 (Spring Boot)

  1. 构建应用: 使用 Maven 或 Gradle 将 Spring Boot 应用打包成可执行的 JAR 文件。 
    # 使用 Maven 打包,跳过测试
    mvn clean package -DskipTests
    
  2. 运行应用: 将生成的 your-app.jar 文件上传到服务器,并通过 Java 命令运行。 
    # 后端服务通常监听在 8080 端口
    java -jar your-app.jar
    

🎨 前端部署 (Vue)

  1. 构建应用: 将 Vue 项目编译打包成静态资源(HTML, CSS, JS)。

    # 生成 dist 目录
    npm run build
    
  2. 托管静态资源: 使用 Nginx 作为 Web 服务器来托管 dist 目录中的文件。

    Nginx 配置示例 (nginx.conf)

    server {
        listen 80; # 监听 80 端口
        server_name your-domain.com; # 你的域名
    
        location / {
            root /path/to/your/vue/dist; # Vue 打包后 dist 目录的路径
            index index.html; # 默认文件
            try_files $uri $uri/ /index.html; # 解决 Vue Router 的 History 模式下刷新 404 的问题
        }
    
        # [推荐] 配置反向代理,解决跨域问题
        location /api {
            proxy_pass http://localhost:8080; # 将所有 /api 开头的请求转发到后端服务
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    

💡 关键点:跨域问题 (CORS)

由于前后端服务部署在不同的源(域名或端口),浏览器会阻止前端直接调用后端 API。解决方案有两种:

  • 后端配置 CORS: 在 Spring Boot 中使用 @CrossOrigin 注解或全局配置来允许特定来源的跨域请求。
  • Nginx 反向代理 (推荐): 如上方案例所示,通过 Nginx 将 API 请求代理到后端服务,对浏览器而言,所有请求都来自同一个源,从而避免了跨域问题。

优点 (✅):

  • 高度解耦: 前后端可以独立开发、测试、升级和扩容。
  • 职责清晰: 前端专注于用户界面,后端专注于业务逻辑。
  • 灵活性高: 可将前端部署到 CDN 以加速访问。

缺点 (❌):

  • 部署稍复杂: 需要分别管理两个服务的部署和运维。
  • 依赖网络: 前后端通信完全依赖网络调用。

2️⃣ 策略二:前后端合并部署

这种方式将前端的静态资源打包进 Spring Boot 项目中,最终只生成一个可部署的 JAR 文件。

📦 打包流程

  1. 构建前端: 在 Vue 项目中执行 npm run build,生成 dist 目录。
  2. 复制资源: 将 dist 目录下的所有文件复制到 Spring Boot 项目的 src/main/resources/static/ 目录下。
    • 原理: Spring Boot 默认会将 resources/static/ 目录下的内容作为静态资源对外提供访问。
  3. 构建后端: 正常使用 mvn clean package 打包 Spring Boot 应用。
  4. 部署运行: 运行生成的单个 JAR 文件,Spring Boot 内嵌的 Web 服务器(如 Tomcat)会同时提供 API 服务和前端页面。 Bash

    java -jar your-app.jar
    

优点 (✅):

  • 部署简单: 只需管理一个 JAR 包,部署流程极大简化。
  • 无跨域问题: 前后端同源,天然避免了 CORS 问题。
  • 管理方便: 前后端版本统一,便于小型项目或单人开发。

缺点 (❌):

  • 紧密耦合: 前后端技术栈绑定,不利于独立演进。
  • 包体积大: 前端资源会增大 JAR 包的体积,可能影响启动和部署速度。
  • 更新不便: 任何前端的微小改动都需要重新打包和部署整个后端服务。

3️⃣ 策略三:容器化部署 (Docker)

这是一种现代化、标准化的部署方式,将前后端应用分别打包成独立的 Docker 镜像,实现环境隔离和轻松迁移。

🐳 容器化流程

  1. 后端容器化:

    • 创建 Dockerfile: Dockerfile
      # 使用一个精简的 Java 基础镜像
      FROM openjdk:11-jre-slim
      # 将打包好的 JAR 文件复制到容器中
      COPY target/your-app.jar /app.jar
      # 暴露端口
      EXPOSE 8080
      # 容器启动时执行的命令
      CMD ["java", "-jar", "/app.jar"]
      
    • 构建镜像: docker build -t your-backend-image .
  2. 前端容器化:

    • 创建 Dockerfile (使用 Nginx 托管): Dockerfile

      # 阶段一:构建 Vue 应用
      FROM node:lts-alpine as build-stage
      WORKDIR /app
      COPY package*.json ./
      RUN npm install
      COPY . .
      RUN npm run build
      
      # 阶段二:使用 Nginx 提供服务
      FROM nginx:stable-alpine
      # 从构建阶段复制打包好的文件
      COPY --from=build-stage /app/dist /usr/share/nginx/html
      # [可选] 复制自定义的 Nginx 配置文件
      # COPY nginx.conf /etc/nginx/conf.d/default.conf
      EXPOSE 80
      CMD ["nginx", "-g", "daemon off;"]
      
    • 构建镜像: docker build -t your-frontend-image .
  3. 编排与运行 (Docker Compose)

    使用 docker-compose.yml 可以一键启动和管理前后端两个容器。

    version: '3.8'
    services:
      backend:
        image: your-backend-image
        ports:
          - "8080:8080"
        # 其他配置,如数据库连接、环境变量等
    
      frontend:
        image: your-frontend-image
        ports:
          - "80:80" # 将容器的 80 端口映射到主机的 80 端口
        depends_on:
          - backend # 确保后端服务先启动
    
    • 一键启动: docker-compose up -d

优点 (✅):

  • 环境一致性: 彻底解决 "在我电脑上是好的" 问题。
  • 易于扩展和迁移: 可以在任何支持 Docker 的环境中快速部署和水平扩展。
  • 标准化: 是通往 CI/CD 和微服务架构的必经之路。

缺点 (❌):

  • 学习成本: 需要掌握 Docker 和 Docker Compose 的基本知识。
  • 资源占用: Docker 本身会占用一定的系统资源。

🌟 部署策略对比与选择建议

特性分离部署合并部署容器化部署 (Docker)
部署复杂度中等简单 👍较高 (初次配置)
耦合度低 (解耦) 👍高 (耦合)低 (解耦) 👍
灵活性/扩展性 👍非常高 👍👍
跨域处理需要 (Nginx/后端CORS)无需 👍需要 (同分离部署)
适用场景大多数生产项目敏捷开发、小型项目、内部系统所有规模的项目,特别是中大型和生产环境 👍

💻 代码演练:三种部署方式

  为了让理论更具体,我们通过一个简单的“Hello World”项目来实际演示这三种核心部署策略。

通用准备 (Prerequisites)

我们假设已有两个基础项目:

  1. 后端 (Spring Boot): 一个名为 ruoyi-system 的项目。
  2. 前端 (Vue): 一个标准的 Vue 项目。

后端 API 示例

在 Spring Boot 项目中,我们创建一个简单的 Controller 提供 API 接口。这个接口将在所有三个示例中被调用。

HelloController.java:

@RestController
@RequestMapping("/api")
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello from Spring Boot! Welcome!";
    }
}

示例 1:🚀 前后端分离部署

这是最灵活的生产模式,前后端各司其职。

⚙️ 后端操作
  1. 打包: 进入 ruoyi-system 项目根目录,执行打包命令。 
    mvn clean package -DskipTests
    
  2. 部署与运行: 将 target/ruoyi-system.jar 上传到服务器,并启动。

    java -jar ruoyi-system.jar
    # 后端服务现在运行在 http://localhost:8080
    
🎨 前端操作
  1. 修改 API 请求代码 (关键)

    为了让生产环境的 Nginx 代理生效,前端代码中应使用相对路径来请求 API,而不是写死的 localhost。

    src/App.vue:

    代码段
    <template>
      <div id="app">
        <h1>{{ message }}</h1>
        <button @click="fetchMessage">Get Message</button>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          message: 'Click the button to fetch data.'
        };
      },
      methods: {
        fetchMessage() {
          // 使用相对路径,Nginx 会捕获 /api 并转发
          fetch('/api/hello')
            .then(res => res.text())
            .then(data => {
              this.message = data;
            })
            .catch(err => {
              this.message = 'Failed to fetch: ' + err;
            });
        }
      }
    };
    </script>
    
  2. 打包: npm run build,生成 dist 目录。

  3. 部署: 将 dist 目录内容上传到服务器,并使用 Nginx 托管。

  4. 配置 Nginx:

    Nginx 的配置是连接前后端的桥梁。

    nginx.conf 示例:

    Nginx
    server {
        listen 80; # 前端对外暴露的端口
        server_name your_domain.com;
    
        # 托管前端静态文件
        location / {
            root /path/to/vue/dist;
            try_files $uri $uri/ /index.html;
        }
    
        # 将所有 /api 请求反向代理到后端服务
        location /api {
            proxy_pass http://localhost:8080; # 后端服务的地址
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
    

    当用户访问页面并点击按钮时,浏览器请求 http://your_domain.com/api/hello,Nginx 接收到请求后,发现它匹配 /api 路径,于是将请求无缝转发给 http://localhost:8080/api/hello


示例 2:📦 前后端合并部署

将前端打包成静态资源,塞入 Spring Boot 项目中,实现单体部署。

⚙️ 后端与前端集成操作
  1. 前端打包: 在 Vue 项目中执行 npm run build

  2. 修改前端代码: 与分离部署一样,API 请求也应使用相对路径,因为最终前后端在同一个源下。fetch('/api/hello') 的写法在这里同样适用。

  3. 复制文件: 将 Vue 打包生成的 dist/ 目录下的所有内容复制到 Spring Boot 项目的 src/main/resources/static/ 目录下。

  4. 打包 Spring Boot:

    mvn clean package -DskipTests
    

    现在生成的 ruoyi-system.jar 文件同时包含了后端代码和所有前端静态资源。

🚀 部署

只需将这个增强版的 JAR 文件上传到服务器并运行即可。

java -jar ruoyi-system.jar

现在,访问 http://your_server_ip:8080,你将直接看到 Vue 应用界面。点击按钮,请求 http://your_server_ip:8080/api/hello 会被同一个 Spring Boot 服务处理,无需任何代理和跨域配置。


示例 3:🐳 Docker 容器化部署

使用 Docker Compose 编排前后端两个容器,实现优雅、隔离的部署。

📁 推荐项目结构
my-project/
├── backend/            # Spring Boot 项目
│   ├── src/
│   ├── pom.xml
│   └── Dockerfile      <-- 后端 Dockerfile
│
├── frontend/           # Vue 项目
│   ├── src/
│   ├── package.json
│   ├── Dockerfile      <-- 前端 Dockerfile
│   └── nginx.conf      <-- 前端 Nginx 配置
│
└── docker-compose.yml  <-- Docker 编排文件
📄 配置文件
  1. 后端 Dockerfile (backend/Dockerfile):

    Dockerfile
    FROM openjdk:11-jre-slim
    # 将 target 目录下的 jar 包复制到容器中,并重命名
    COPY target/ruoyi-system.jar /app.jar
    # 容器启动时运行 jar 包
    CMD ["java", "-jar", "/app.jar"]
    
  2. 前端 Nginx 配置 (frontend/nginx.conf) (关键!):

    这个 Nginx 配置是给容器内部使用的,它将 API 请求转发给名为 backend 的服务。

    Nginx
    server {
        listen 80;
        location / {
            root /usr/share/nginx/html;
            try_files $uri $uri/ /index.html;
        }
        location /api {
            # 这里的 "backend" 是 docker-compose.yml 中定义的服务名
            # Docker 的内部 DNS 会将其解析到后端容器的 IP
            proxy_pass http://backend:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
    
  3. 前端 Dockerfile (frontend/Dockerfile):

    这个 Dockerfile 会先构建 Vue 应用,然后将构建结果和 Nginx 配置一起打包。

    Dockerfile

    # --- 构建阶段 ---
    FROM node:lts-alpine as build-stage
    WORKDIR /app
    COPY package*.json ./
    RUN npm install
    COPY . .
    RUN npm run build
    
    # --- 生产阶段 ---
    FROM nginx:stable-alpine
    # 从构建阶段复制打包好的静态文件
    COPY --from=build-stage /app/dist /usr/share/nginx/html
    # 复制自定义的 Nginx 配置文件
    COPY nginx.conf /etc/nginx/conf.d/default.conf
    EXPOSE 80
    CMD ["nginx", "-g", "daemon off;"]
    
  4. Docker Compose (docker-compose.yml):

    YAML
    version: '3.8'
    services:
      backend:
        build: ./backend  # 指定后端项目的构建上下文
        ports:
          - "8080:8080"   # 将容器的8080端口映射到主机的8080端口
        restart: always
    
      frontend:
        build: ./frontend # 指定前端项目的构建上下文
        ports:
          - "80:80"       # 将容器的80端口(Nginx)映射到主机的80端口
        restart: always
        depends_on:       # 确保后端服务先于前端启动
          - backend
    
🚀 启动

在项目根目录(my-project/)下,执行一个命令即可启动所有服务:

docker-compose up -d --build
  • up: 创建并启动容器。
  • -d: 后台运行。
  • --build: 在启动前构建镜像。

        现在,访问你服务器的公网 IP 或域名,就可以看到由 Docker 运行的前端应用,并且它能成功调用同样由 Docker 运行的后端服务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值