基于springboot+vue的前后端分离后项目部署方案

在传统模式下,项目部署只可能是后端开发人员的事,与前端开发人员没有什么关系。而前后端分离后,可能会有些许改变。

常见的部署方案如下:

一、前后端一起部署,前端打包成静态文件,拷贝到后端项目中,然后部署后端项目。

二、前后端分开部署,前端使用nginx部署,后端单独运行,然后使用nginx反向代理。

三、前后端分开部署,前端扔在cdn,后端单独运行。

本文重点讲一下方案一和方案二,限定条件:路由模式-history

部署原理:

  1. 如果访问路径对应的文件存在,则返回对应文件;
  2. 如果访问路径对应的文件不存在,则返回index.html

部署方案一(springboot+vue)

  1. 后端新增控制器处理如下:
// 这里用到了模板引擎thymeleaf(当然,别的模板引擎也行)
@Controller
public class IndexController {
	@GetMapping("/ui/**") // 所有的/ui/** 返回index.html页面
	public ModelAndView ui() {
		return new ModelAndView("/index.html");
	}
	@GetMapping("/") // 访问根目录,要转发到上面的请求
	public ModelAndView index() {
		return new ModelAndView("forward:ui");
	}
}

注意:这里的/ui/主要是为了方便区分是否为前端路由,和前端的路由的base保持一致。

  1. 前端路由文件处理如下:
const router = new VueRouter({
  base:"/ui/", // 这里要和控制层那里配置一致
  mode:'history',
  routes: [
    {
      path:'/',
      name:'home',
      component: () => import('@/views/home.vue')
    },
    {
      path:'/about',
      name:'about',
      component: () => import('@/views/about.vue')
    }
  ]
部署流程
  1. 将前端工程进行打包,生成文件在dist目录下
  2. 将前端打包的dist/**的所有文件(除index.html外)复制到src/main/resources/static目录下(springboot静态文件目录)
  3. 将前端打包的dist/index.html文件复制到src/main/resources/templates(模板引擎模板根目录)
  4. maven打包生成jar包
  5. 发布
    这里推荐一个maven打包插件
<!--资源插件,主要为了从前端项目里复制打包好的文件到springboot项目-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy static</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>src/main/resources/static</outputDirectory>
                            <overwrite>true</overwrite>
                            <resources>
                                <resource>
                                    <!--因为vue-cli打包的目录在项目的根目录,所以从这里复制-->
                                    <directory>/java_projects/${project.artifactId}/dist</directory>
                                    <includes>
                                        <include>css/</include>
                                        <include>img/</include>
                                        <include>fonts/</include>
                                        <include>js/</include>
                                        <include>favicon.ico</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                    <execution>
                        <id>copy template</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>src/main/resources/templates</outputDirectory>
                            <overwrite>true</overwrite>
                            <resources>
                                <resource>
                                    <!--因为vue-cli打包的目录在项目的根目录,所以从这里复制-->
                                    <directory>/java_projects/${project.artifactId}/dist</directory>
                                    <includes>
                                        <include>index.html</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

部署方案二(nginx+springboot+vue)

nginx配置如下:

server {
        listen       80;
        server_name  localhost;
        root /java_projects/project_name/dist; # 前端打包目录
        location / {
            try_files $uri $uri/ @router; # 存在文件,返回文件,不存在,由@router处理
            index index.html;
        }
        location @router {
            rewrite ^.*$ /index.html last; # 所有请求,返回index.html
        }
        location /api { # 为了访问统一处理,前端也要修改
            rewrite /api/(.*) /$1 break; # 重写请求(后端并无/api前辍)
            proxy_pass http://127.0.0.1:18080; # 接口地址
        }
}

或者不重写,url加/

server {
        listen       80;
        server_name  localhost;
        root /java_projects/project_name/dist; # 前端打包目录
        location / {
            try_files $uri $uri/ @router; # 存在文件,返回文件,不存在,由@router处理
            index index.html;
        }
        location @router {
            rewrite ^.*$ /index.html last; # 所有请求,返回index.html
        }
        location /api/ { # 为了访问统一处理,前端也要修改
            proxy_pass http://127.0.0.1:18080/; # 接口地址
        }
}

前端修改如下:

axios.defaults.baseURL='/api'; // 该配置与nginx配置一致