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

时间:2017-01-29 16:40:06

标签: node.js angular heroku spring-boot npm

我有Spring Boot作为后端,Angular2作为前端。我想分别开发它们并部署到Heroku

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

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

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

  2. 运行服务器以专门提供Angular应用程序,该应用程序将与Spring应用程序通信(此处出现CORS问题?)因此总共有两台服务器

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

    第二种方法是矫枉过正,因为我有两台服务器(例如TomcatNode.js)。如果我可以将Angular放在Angular内,为什么我的服务器应该包含Spring应用?

    是否有更合理的方式来提出上述内容?

    感谢。

3 个答案:

答案 0 :(得分:7)

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

--spring.resources.static-locations=<url>

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;
                }
            }
        }
    }
}

答案 1 :(得分:3)

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

此选项是基于MicroServices的体系结构中的推荐选项,其中各个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文件夹复制到resources文件夹下的Spring Boot静态文件夹。 (在.gitignore文件中排除静态文件夹,以便Angular分发文件不会与REST API一起检入源代码控制中。)

现在,随着Java构建的开始,它将自动包含fat jar中的静态文件夹,该文件夹现在将同时提供API和Angular UI。

答案 2 :(得分:2)

到目前为止,我使用一个git存储库创建了使用angular和spring-boot的应用程序,但是有两个不同的maven项目,一个用于后端,一个用于前端。

使用Maven,我构建了一个带有嵌入式Tomcat的胖jar并将其部署到Amazon EC2。

我也尝试过Heroku,你可以在那里部署相同的胖罐。

对于下一个项目,我会采用另一种方法,将所有静态资源(如html,javascript等)部署到Amazon S3,并将spring-boot应用程序部署到像heroku这样的提供程序。

这种方式的前端部署似乎更容易,更快,更便宜。

还有一篇关于Using AWS S3 to Store Static Assets and File Uploads

的博客文章