首页 > 解决方案 > 如何将 Spring Boot Rest 服务和 Angular App 捆绑在一个 war 文件中

问题描述

遇到了一种情况,我需要使用 Angular 应用程序部署单个 war 文件,该应用程序在同一个 war 文件中使用 REST API。与同一服务器中的 REST API 通信时出现 CORS 错误。

ex Angular 应用程序位于:localhost:8080/UIApp 和 REST 服务位于:localhost:8080/RESTService,内部服务 URL 已正确使用(localhost:8080/RESTService)

如何在部署后正确配置,使用服务的角度应用程序位于由 war 文件提取的同一文件夹中。

标签: angularspring-boottomcat

解决方案


这里有几点需要注意。即使您仅通过 --prod 选项将 Angular 应用程序捆绑在 {your-app}\WEB-INF\classes\static 文件夹中,也会存在 CORS 问题,因为 Angular 应用程序会考虑服务器内的基本目录。因此,您需要使用 CLI 使用以下命令构建应用程序:

ng build --base-href=/{your-app}/ 这将确保 dist 文件夹中的文件将像它们在 {your-app} 文件夹中一样使用(HTTP://localhost:8080/{your-app }")。请注意,您需要与服务器中提取的战争文件夹具有相同的名称。

现在我们终于需要在 Spring Boot 应用程序的 pom 文件中添加一个插件,以便它将 dist 文件夹内容复制到 \WEB-INF\classes\static 文件夹。

添加以下插件:

  <plugin>
      <artifactId>maven-resources-plugin</artifactId>
      <executions>
        <execution>
          <id>copy-resources</id>
          <phase>validate</phase>
          <goals><goal>copy-resources</goal></goals>
          <configuration>
            <outputDirectory>${basedir}/target/classes/static/</outputDirectory >
            <resources>
              <resource>
                <directory>${basedir}/../toAngularAppDir</directory >
              </resource>
            </resources>
          </configuration>
        </execution>
      </executions>
    </plugin>

以上步骤将配置 Angular 页面以加载到您的 {your-app} 上。但是还有一个步骤可以阻止 REST 应用程序在 Angular 应用程序导航时尝试查找资源。

为此,我们需要添加如下 Web 配置:

添加一个名为 config (com.youdomain.config) 的包,然后添加一个 websecurity 配置器:

 @Configuration
 public class MvcConfiguration implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
        .addResourceLocations("classpath:/static/")
        .resourceChain(true)
        .addResolver(new PathResourceResolver() {
            @Override
            protected Resource getResource(String resourcePath, Resource location) throws IOException {
                Resource requestedResource = location.createRelative(resourcePath);

                return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
                        : new ClassPathResource("/static/index.html");
            }
        });
    }
}   

推荐阅读