【问题标题】:Package Sinatra app into a single JAR file?将 Sinatra 应用程序打包成一个 JAR 文件?
【发布时间】:2014-09-17 20:27:00
【问题描述】:

我有一个明显(愚蠢的)简单问题:

使用 JRuby 是否可以部署单个文件的 Sinatra 应用程序?

我的意思是:我的 Sinatra 应用程序已将所有需要的 gem 分解到某个 ./vendor/lib 目录中,我想将整个应用程序部署为单个 jar 文件以在部署机器上运行:

$ java jar my_app.jar

我只有 Java。

这可能吗?如果是这样,是否有一种简单的方法可以做到这一点?

TIA

【问题讨论】:

    标签: ruby jruby sinatra


    【解决方案1】:

    您可以尝试为此使用 Warbler。从 1.1 版开始,Warbler 支持将 war 文件设置为“可执行”。详情请见the documentation

    基本上,安装 warbler 并尝试在您的 Sinatra 应用程序上运行它。如果你有一个 config.ru,一切都应该可以正常工作。

    $ jruby -S gem install warbler
    $ jruby -S warble executable war
    $ java -jar my_app.war
    

    【讨论】:

    • TNX,我已经尝试过了......唯一的问题出现在 Bundler 中“安装”了一些 gem(例如:nokogiri)。
    【解决方案2】:

    其实很简单。假设您可以使用命令将所有内容冻结在某个目录下运行您的应用程序:

    ruby myapp.rb
    

    现在您需要将此脚本放入应用程序下的 lib 目录中,并编写一个 java 包装器来加载该脚本。执行此操作的示例代码:

    package livesync;
    
    import org.jruby.Ruby;
    import org.jruby.RubyRuntimeAdapter;
    import org.jruby.javasupport.JavaEmbedUtils;  
    import java.util.ArrayList;
    
    public class LiveSyncRunner {
        public static void main(String[] args) {
            String[] jrubyArgs = new String[3 + args.length]; 
            jrubyArgs[0] = "-e";
            jrubyArgs[1] = "require 'livesync/livesync_wrapper'";
            jrubyArgs[2] = "livesync";
            for (int i = 0; i < args.length; ++i) {
                jrubyArgs[i + 3] = args[i];
            }
            org.jruby.Main.main(jrubyArgs);
        }
    }
    

    如果上面我运行的脚本在 lib/livesync_wrapper.rb 中

    现在您只需要一个合适的 build.xml 文件(放在根目录中) 我的 build.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project basedir="." default="dist" name="Juggernaut">
      <description>Combine Ruby and Java source with the jruby-complete jar</description>
      <target name="dist" description="Create the deliverable jar">
        <taskdef name="jarjar" 
                 classname="com.tonicsystems.jarjar.JarJarTask" 
                 classpath="vendor/jarjar-1.0rc7.jar"/>
        <mkdir dir="pkg"/>
        <jarjar destfile="pkg/livesync.jar">
          <manifest>
            <attribute name="Main-Class" value="livesync.LiveSyncRunner"/>
          </manifest>
          <fileset dir="classes"/>
          <zipfileset dir="vendor/gems" prefix="vendor/gems"/>
          <zipfileset src="vendor/jruby-complete-1.1.2.jar" />
        </jarjar>
      </target>
    </project>
    

    您可能需要在此处更改的内容是:

    • 主类的名称 - 这必须 你的java包装器的很多名字 (加载 ruby​​ 脚本)
    • 添加/删除一些 zipfilesets

    您还需要在 vendor 目录中包含文件 jruby-complete-1.1.2.jar 和 jarjar-1.0rc7.jar。你应该毫无问题地用谷歌搜索它们。

    完成此操作后,您只需转到根目录并运行 ant。在此之后,您可以使用

    运行您的脚本
    java -jar pkg/livesync.jar args1 agrs2 ...
    

    希望这会有所帮助!

    【讨论】:

    • 这看起来真的很棒,但是你能不能把 Ruby Gems 包装成一个库而不是可执行文件。我的意思是我有 ruby​​ 库,其中包含我想从我的 java 服务器代码运行的各种函数/方法 我如何从 Java 中调用 Ruby 函数,包括参数和对象
    • 抱歉,两年来我对java+jRuby一无所知,所以我的知识有点生疏。不管怎样,你可以在这个 gem 源中找到很多这样的例子:github.com/kowalski/redcloth/blob/master/ext/redcloth_scan/… 不要害怕这是一个模板......
    【解决方案3】:

    从一个 jruby 完整的 jar 文件开始;解压罐子。然后,您可以将 gem 安装到分解后的 jar 中。

    META-INF 目录中的jruby.home 是“通常的”jruby 安装所在的位置。您可以使用该目录中的 gem。

    接下来,在 jruby.home 目录下,创建一个目录,我们称之为 app 并将你的应用放入其中。

    接下来,您需要创建一个脚本以在启动您的应用程序的 bin 目录中运行。

    测试并确保一切正常。

    然后将所有内容压缩备份,创建一个文件,例如 app.jar。

    最后,运行:

      java -jar app.jar -S YOUR_SCRIPT
    

    -或- 处理清单并创建一个功能类似于脚本的java类。

    【讨论】:

      猜你喜欢
      • 2019-02-20
      • 1970-01-01
      • 2016-11-08
      • 2013-03-30
      • 2011-10-13
      • 2019-05-12
      • 2015-10-19
      • 2021-02-26
      • 1970-01-01
      相关资源
      最近更新 更多