Angular2和Spring Boot.如何服务前端?

fas*_*sth 6 heroku node.js npm spring-boot angular

我有Spring Boot后端和Angular2前端.我想分别开发它们并部署到Heroku.

它们不应该有任何共同的依赖关系,应该在单独的git-repos中.

据我了解,有两种主要的实现方式:

  1. 运行npm build并将dist文件resource夹复制到Spring应用程序的文件夹中,以便最后将其作为静态内容处理

  2. 运行服务器专门为Angularapp 服务,它将与Springapp 通信(这里出现CORS问题?)所以总共有两台服务器

我认为第一种方式有点"脏",因为我不认为从一个项目到另一个项目的复制文件夹是好的.

而第二种方式是矫枉过正,因为我有两个服务器(TomcatNode.js,例如).Angular如果我可以简单地放入Angular内部,为什么我应该有应用服务器Spring

有没有更合适的方式来提出上述内容?

谢谢.

小智 7

在我的组织中,我们有很多Spring Boot和Angular应用程序.当不需要两个服务器时,Spring Boot可以从任何支持的URL(例如"http:"或"file:")提供静态内容.只需在启动时将此参数传递给您的应用:

--spring.resources.static-locations=<url>
Run Code Online (Sandbox Code Playgroud)

Spring Boot还可以通过包含以下Web MVC配置来支持Angular单页面应用程序路由.这确保即使用户在浏览器中刷新页面,Spring Boot仍将为其他角度路由提供index.html的内容.

public class SinglePageAppWebMvcConfigurer extends WebMvcConfigurerAdapter
{
    @Autowired
    private ResourceProperties resourceProperties;

    private String apiPath = "/api";

    public SinglePageAppWebMvcConfigurer()
    {
    }

    public SinglePageAppWebMvcConfigurer(String apiPath)
    {
        this.apiPath = apiPath;
    }

    protected String getApiPath()
    {
        return apiPath;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        registry.addResourceHandler("/**")
            .addResourceLocations(resourceProperties.getStaticLocations())
            .setCachePeriod(resourceProperties.getCachePeriod()).resourceChain(true)
            .addResolver(new SinglePageAppResourceResolver());
    }

    private class SinglePageAppResourceResolver extends PathResourceResolver
    {
        @Override
        protected Resource getResource(String resourcePath, Resource location) throws IOException
        {
            Resource resource = location.createRelative(resourcePath);
            if (resource.exists() && resource.isReadable()) {
                return resource;
            } else if (getApiPath() != null && ("/" + resourcePath).startsWith(getApiPath())) {
                return null;
            } else {
                LoggerFactory.getLogger(getClass()).info("Routing /" + resourcePath + " to /index.html");
                resource = location.createRelative("index.html");
                if (resource.exists() && resource.isReadable()) {
                    return resource;
                } else {
                    return null;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sap*_*asu 5

选项 1 一个服务器进程托管 REST API,另一个服务器进程托管 Angular UI

此选项是基于微服务的架构中的推荐选项,其中单个 API(或相关的小 API 组)通过将它们托管在单独的服务器进程中来单独运行和扩展。在这种情况下,如果 Angular UI 也与 REST API 捆绑在一起,则意味着 Angular UI 中的每个错误修复或增强都需要重新构建和重新部署您的服务。当我们开始这样做时,它将违背基于微服务的架构的目的。

因此,在这样的架构中,一个或多个服务器实例将仅托管 Angular UI。Angular UI 将依次使用某些服务发现机制通过 API 网关调用各个 API。然而,基于微服务的架构并非微不足道——它很复杂,有很多活动部件。对于大型项目来说,这种复杂程度是合理的。

选项 2 一个服务器进程同时托管 REST API 和 Angular UI

对于用户群为几百用户的中小型项目,此选项是推荐的选项。

在此类项目中,创建一个存储库,其中 Maven 项目将包含两个子模块 - 一个用于 REST API,另一个用于 Angular UI。

使用 Maven 插件“frontend-maven-plugin”来构建 UI 部分。这将自动下载指定的 NodeJs 版本并调用适当的 npm 命令来构建 Angular 项目。最后,使用 Maven 元素将 Angular dist 文件夹复制到资源文件夹下的 Spring Boot 静态文件夹。(在 .gitignore 文件中排除静态文件夹,以便 Angular 分发文件不会与 REST API 一起检入源代码管理)。

现在,当 Java 构建开始时,它会自动在 fat jar 中包含静态文件夹,该文件夹现在可以同时为 API 和 Angular UI 提供服务。