运行grunt和tomcat服务器的Web App(Spring,Angular,Grunt,Maven,Tomcat)

时间:2014-08-01 18:55:13

标签: java spring angularjs gruntjs maven-tomcat-plugin

好的,所以我一直在阅读其他几个堆栈问题并尝试将它们拼凑在一起而没有太多运气。基本上我的方法是我目前有一个项目有多个子项目。我基本上有以下内容:

root
|----backend
|----|----src
|----|----|----main
|----|----|----|----java (individual java files not shown)
|----|----|----|----resources
|----|----|----|----|----META-INF
|----|----|----|----|----|----applicationContext.xml
|----|----|----|----webapp
|----|----|----|----|----WEB-INF
|----|----|----|----|----|----web_servicesConfig.xml
|----|----|----|----|----|----web.xml
|----|----pom.xml
|----deploy
|----|----src
|----|----|----main
|----|----|----|----resources (properties files for tomcat)
|----|----pom.xml
|----frontend
|----|----app
|----|----|----angular files
|----|----bower_components
|----|----|----bower files
|----|----bower.json
|----|----Gruntfile.js
|----|----pom.xml

好的希望在文件结构上足够清楚。我打算使用maven-grunt-plugin,所以我可以在前端运行我的grunt命令。前端基本上与角度产生的设置相同或者至少是目标。部署只是设置tomcat,后端保存Spring 4 restful services / api。

好的,这就是我很困惑并寻求帮助。我不知道如何让前端与后端正常工作。基本上我想知道是否有办法告诉maven以启动模式启动Tomcat和Grunt服务器,以便我可以使用它们的两个功能来快速开发我的项目,然后将min文件拉入生产构建的战争中。我想我无法弄清楚如何让一切都很好地融合在一起。我查看了这个问题,但是我仍然感到困惑:

How to deploy AngularJS app and Spring Restful API service on the same domain/server?

我很喜欢任何教程的链接,这些教程解决了如何将maven与tomcat,spring,angularjs和grunt一起使用...也是bower所以我可以将它用于我的前端包管理。我已经阅读了几个例子,并且已经看到很多关于如何在Java EE和jsp中使用spring的讨论。或者使用Gradle来做我想要的一些事情......但是没有像我正在尝试的那样。

当然,如果这是一个糟糕的方法让我知道。基本上我想让我的子项目尽可能分开,同时仍允许开发人员从一个pom文件导入/运行。

2 个答案:

答案 0 :(得分:8)

从你的问题我只挖了两个问题

  1. 如何使用grunt / bower + tomcat进行持续开发
  2. 如何部署生产
  3. 1 - 持续发展

    我选择的解决方案 - 因为您已经使用api来传达client <-> server - 是完全分开两个项目。

    那是什么意思? 对我来说是拥有两个不同的存储库。一个用于客户端,一个用于服务器 这样你获得的好处很少:

    • 拆分项目的工作(前端/服务器端)
    • 易于维护
    • 如果您想支持“仅API”,请参阅示例,移动应用程序等。

    但是 - 他们在开发时如何沟通?

    这是一个很好的问题: 一种解决方案是并行地在localhost上运行两个服务器,即mvn clean tomcat:run -P yourprofile; grunt server

    但是 - 如果我尝试从不同端口从客户端访问服务器端,我将获得跨域? 你是对的。在这里你得到了grunt及其插件的帮助。抓取grunt-connect-proxy

    的副本

    这个插件有什么好处,它充当grunt服务器和tomcat服务器之间的中间件,所以你问grunt服务器的API,但实际上grunt要求tomcat服务器回答(当然在幕后)

    2 - 部署以进行生产

    我想这是个人偏好问题。我发现war文件非常大,一次又一次上传(即使能够在你所有的tomcat应用程序之间共享lib)。我想出的解决方案是通过git进行部署。

    好的,但我有一个大战争档案。我怎么能这样做?

    对我来说,我使用的是我在bash中编写的部署脚本。这就是它的作用:

    1. 标记当前来源
    2. 运行mvn clean package war:爆炸-P your-prod-profile(这也将运行测试和集成测试)
    3. 使用上面的命令,您可以在一个地方获得所有已编译项目的文件,而不是一个大型战争文件。
    4. 将所有这些文件(和内部路径)复制到外部文件夹中(我使用另一个存储库通过git进行维护部署。所以基本上我有3个存储库。一个用于服务器源,一个用于客户端源,一个用于服务器二进制文件。)
    5. 在做4之前,请确保从中删除所有文件和文件夹(除了.git之外的东西)
    6. 4之后做“git add -A”
    7. “git commit -a -m'new production version X”
    8. 您可以在之前和之后标记一些标记,以便在新制作中存在大错误的情况下轻松恢复最后一个代码
    9. 在服务器上运行远程命令到。)停止服务器,b。)从二进制存储库中提取最后的更改,c。)再次运行服务器。
    10. 对我来说,我所做的是tomcat应用程序与外部文件夹(二进制存储库)之间的符号链接所以
    11. 希望这会给你一些指示,

      贝斯茨, 橡木

答案 1 :(得分:2)

好的,所以我想发布一个适合我本地开发的解决方案,并允许我使用所需的方法......就像Oak所说的那样(抱歉我不知道如何链接他的用户名)并有两个单独的构建/项目。但是,我的前端项目使用grunt在特定端口上提供我的代码,其中一些中间件将端口上的请求定向到前端代码或运行spring-boot的服务器。这使我可以表现为代码实际上在同一个项目上运行,并避免任何CORS和其他问题在不同的域/服务器上运行它们。这是我的grunt构建中允许我这样做的代码部分:

livereload: {
    options: {
      debug: true,
      middleware: function (connect, options) {
        var middlewares = [];

        middlewares.push(rewriteModule.getMiddleware([
          //Load App under context-root of 'myappcontext/secured'
          {from: '^/napiweb/(.*)$', to: '/$1'},

          //Redirect slash to myappcontext/secured as convenience
          {from: '^/$', to: '/napiweb', redirect: 'permanent'}

          //Send a 404 for anything else
          //{from: '^/.+$', to: '/404'}
        ]));

        if (!Array.isArray(options.base)) {
          options.base = [options.base];
        }

        options.base.forEach(function () {
          // Serve static files.
          middlewares.push(connect.static('.tmp'),
            connect().use(
              '/bower_components',
              connect.static('./bower_components')
            ),
            connect.static(appConfig.app));
        });

        // Make directory browse-able.
        //middlewares.push(connect.directory(directory));

        return middlewares;
      }
    }
  },

然后我将spring-boot配置为具有本地开发的代理,该代理将特定请求转发到前端。它设置如下:在我的config.xml文件

<config proxy-port="{{http-port}}" console-port="1776">
  <console-recording sso="true" rest="true" max-entries="100" enable-debug- logging='true'/>
  <sso-cookie name="wamulator" domain=".somedomain.com" session-timeout-seconds="1800"/>
  <port-access local-traffic-only="false"/>
  <sso-traffic strip-empty-headers="true">
     <by-site host="localhost.somedomain.com" port="{{http-port}}">

       <cctx-mapping thost="127.0.0.1" tport="8081">
         <policy-source>xml={{policy-src-xml}}</policy-source>
       </cctx-mapping>
       <cctx-mapping thost="127.0.0.1" tport="9000">
         <policy-source>xml={{static-src-xml}}</policy-source>
       </cctx-mapping>
       <cctx-mapping thost="127.0.0.1" tport="8180">
         <policy-source>xml={{napi-src-xml}}</policy-source>
       </cctx-mapping>
     </by-site>
  </sso-traffic>

 <user-source type='xml'>xml={{usr-src-xml}}</user-source>
 <proxy-timeout inboundMillis="0" outboundMillis="0" />
</config> 

正如您所看到的,cctx映射会将一些请求指向前端,在端口9000上提供服务,一些请求指向后端提供API.This基于policy-config.xml和static-config.xml文件。它们几乎完全相同,唯一的区别在于authHost和cctx设置,例如:

<deployment at='2013-01-31_16:25:12.205-0700'>
   <environment id='dev' host='dev.somedomain.com (exposee)'/>
   <application id='napi-rest' authHost='localhost.somedomain.com/napiweb/api' cctx='/napiweb/api'>
   <authentication scheme='anonymous' name='Anonymous Authentication'> </authentication>
   <authorization failure-redirect-url='/denied.html'>
   <default format='exposee' value='Allow Authenticated Users'>
     <headers>
       <success>
         ...profile-att specific for my organization
       </success>
       <failure>
         <redirect value='/denied.html'/>
       </failure>
     </headers>
  </default>
  <rule name='Allow Authenticated Users' enabled='true' allow-takes-precedence='false'>
    <allow>
      <condition type='role' value='Anyone'/>
    </allow>
  </rule>
</authorization>

唯一的另一个区别是另一个文件有authHost='localhost.somedomain.com/napiweb/' cctx='/napiweb/'这会导致调用API并调用前端,就好像它们是从同一个项目中提供的一样。然后,当我们将项目推送到我们的存储库时,我们有两个构建周期。一个接管前端并使用grunt build创建静态资产,然后将这些文件复制到其余服务器,以便它们可以为它们提供服务。这允许我们为开发提供单独的项目,但是为我们的站点提供服务的单个服务器。不理想......最终我认为我们应该为正面和背面设置单独的服务器/实例,但由于我们不允许这样做,这使我们可以像在开发过程中那样行事。我希望这可以帮助别人。