如何将 Spring Boot Rest 服务和 Angular App 捆绑在一个 war 文件中

Posted

技术标签:

【中文标题】如何将 Spring Boot Rest 服务和 Angular App 捆绑在一个 war 文件中【英文标题】:How to bundle Spring Boot Rest service and Angular App in a single war file 【发布时间】:2021-02-03 19:00:44 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

这里有几点需要注意。即使您仅通过 --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")。请注意,您需要与您的名称相同war 文件夹被提取到服务器中。

现在我们最终需要在 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");
            
        );
    
   

【讨论】:

以上是关于如何将 Spring Boot Rest 服务和 Angular App 捆绑在一个 war 文件中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot REST 应用程序中重用类?

如何在 Spring Boot 服务应用程序中的 REST 服务调用之间按原样传递请求参数?

Spring Boot webservice (REST) - 如何将 JUnit 5 测试从基本身份验证更改为 OAuth2 (Keycloak)

我可以使用 REST Web 服务和 Spring Boot 将 servlet 中的应用程序转换为 Spring 吗?

如何正确实现使用 Spring MVC\Boot 返回图像列表的 REST 服务?

如何将 spring security 与 rest oauth2 服务和 spring social 集成?