Skip to content

在 SpringBoot 中部署 vue3 工程

前端打包设置

js
import { createRouter, createWebHistory } from "vue-router";

// 此处省略其他代码

// 路由根路径:'/relx/'; 为什么设置路由根路径?避免路由路径和后台接口路径一样,当刷新页面时变成调用后台接口而返回 JSON 的问题。
// 部署到 nginx 服务器下,我们一般 router 的 hitory 使用 createWebHistory 来去掉 url 中的 #
// 但如果要打包并部署到 springboot 下的 static 目录,默认只能用 createWebHashHistory 才不会有问题。
// 但我们又想使用 createWebHistory 模式,还不想刷新时出现页面 404 的问题,此时需要在后端处理了。
// 参考 java 类:NotFoundErrorPageRegistrar.java
const router = createRouter({
  history: createWebHistory("/relx/"),
  routes,
});

后台方案一:添加 WebServerFactoryCustomizer

java
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
    return (factory -> {
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
        factory.addErrorPages(errorPage404);
    });
}

后台方案二:添加 NotFoundErrorPageRegistrar 类

java
package com.github.mengweijin.relx.config;

import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

/**
 * Vue 项目打包部署到 nginx 服务器下,我们一般 router 的 hitory 使用 createWebHistory 来去掉 url 中的 #
 * 但如果要打包并部署到 springboot 下的 static 目录,默认只能用 createWebHashHistory 才不会有问题。
 * 如果使用 createWebHistory,访问页面也没问题,但是刷新一下页面就 404 了。
 *
 * 但我们又想使用 createWebHistory 模式,还不想刷新时出现页面 404 的问题,所有在这里处理一下。
 *
 * @author mengweijin
 * @date 2022/5/2
 */
@Component
public class NotFoundErrorPageRegistrar implements ErrorPageRegistrar {
    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
        registry.addErrorPages(error404Page);
    }
}

前端打包 dist 文件夹

使用 vue-cli 打包 vue 前端项目后,生成的打包后的前端项目目录结构如下:

txt
dist
    css
    fonts
    img
    js
    favicon.ico
    index.html

注:后端不需要引入 spring-boot-starter-thymeleaf 就可以运行的。因此没必要引入多余的 jar。

前端部署方式一:部署到 resources/static 目录

将上面的目录复制到 spring boot 项目的 resources/static 目录下,目录结构如下:

txt
resources
    static
        css
        fonts
        img
        js
        favicon.ico
        index.html

启动 spring boot 项目,访问页面 http://localhost:8080/index.html 即可。

前端部署方式一:部署到 resources/dist 目录

后端添加资源映射:

java
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 将根路径 "/" 的请求转发到 "/index.html"
        registry.addViewController("/").setViewName("forward:/index.html");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 添加资源处理器,用于映射静态资源路径
        registry.addResourceHandler("/**").addResourceLocations("classpath:/dist/");
    }
}

将上面的目录复制到 spring boot 项目的 resources/dist 目录下,目录结构如下:

txt
resources
    dist
        css
        fonts
        img
        js
        favicon.ico
        index.html

启动 spring boot 项目,访问页面 http://localhost:8080/ 即可。

常见问题

vue element-ui icon 打包后放在 springboot 中 icon 没有显示的问题

参考博客(只需要看后半段,前半段不对):https://blog.csdn.net/dylin83/article/details/115090256

SpringBoot maven 配置

xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <configuration>
                <nonFilteredFileExtensions>
                    <!-- 支持字体库 -->
                    <!--vue element-ui icon打包后放在springboot中icon没有显示的问题-->
                    <!--参考博客(只需要看后半段,前半段不对):https://blog.csdn.net/dylin83/article/details/115090256-->
                    <!--上面的配置就造成了springboot 用maven打包时把resource进行了filter,字库文件被修改了!!-->
                    <!--解决方案:让ttf和woff文件不要filter-->
                    <!-- 不要过滤字体库,会造成字体库内容变化,显示不了 -->
                    <nonFilteredFileExtension>woff</nonFilteredFileExtension>
                    <nonFilteredFileExtension>woff2</nonFilteredFileExtension>
                    <nonFilteredFileExtension>eot</nonFilteredFileExtension>
                    <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
                    <nonFilteredFileExtension>svg</nonFilteredFileExtension>
                </nonFilteredFileExtensions>
            </configuration>
            <version>3.0.2</version>
        </plugin>
    </plugins>
</build>