在 Ruby on Rails 应用程序中重用 Java 代码

简介: 在 Ruby on Rails 应用程序中重用 Java 代码

开始之前

关于本教程

Ruby on Rails (Rails) 是用 Ruby 编写的一个 full-stack Web 应用程序框架,而 Ruby 是一种功能丰富的、免费的、可扩展的、可移植的、面向对象的脚本编制语言。Rails 在 Web 应用程序开发人员之间非常流行。通过它,可以快速有效地开发 Web 应用程序,并将其部署到任何 Web 容器中,例如 IBM® WebSphere® 或 Apache Tomcat。

在 Rails 和类似的 Web 应用程序开发框架出现之前,用于 Web 应用程序开发的标准工具是 Java 语言,因为 Java 语言是独立于平台的,并且有完整的 API 集。很多 Java Web 应用程序仍然在运行,这导致很多非常有用的、编写良好的 Java 代码(在本教程中统称遗留 代码)具有良好的可用性。遗留 Java 代码通常被打包在一组 JAR 文件。

如果将 Web 应用程序开发平台改为 Rails,那么可以重用遗留 Java 代码。Ruby Java Bridge (RJB) 是一个工具包,通过它可以将 JAR 文件装载到 Rails 应用程序中,还可以在 Rail 应用程序中访问其中的方法和变量。本教程解释如何在 Rails 应用程序中配置和使用 RJB。

目标

在本教程中,您将学习如何:

  • 下载、编译和安装 RJB
  • 设置 RJB 以访问共享 Java 库
  • 将遗留 Java 代码装载到 Rails 应用程序中并进行访问

本教程并不深入研究 Rails 的功能。与其他 Web 框架相比,Rails 有很多优点,其中一个优点就是用于该平台的文档的数量和质量都很高(参见 参考资料)。

先决条件

本教程假设读者基本熟悉 Java 语言、Ruby 和 Ruby on Rails。

系统需求

本教程假设您使用 Linux® 系统(但是,在 Windows® 上的步骤基本上是相同的)。本教程假设您有一个可以工作的 Ruby on Rails。如果还没有,请在 参考资料 小节中找到相关文档的链接,以帮助您在自己的系统上安装和配置 Rails。

RJB 要求系统上安装有 Java SDK。如果需要一个 Java SDK,可以针对您的平台下载最新的 Java SE SDK,并马上安装它。

RJB 安装和设置

本节带您亲历 RJB 的下载、安装、编译和设置。

下载 RJB

可以下载标准 Ruby Gem 包或自己编译的源代码归档文件形式的 RJB。为了进行演示,我推荐下载源代码归档文件,所以我将使用这种方法。闲话少说,现在就 下载 RJB 1.1.3 source .zip 文件(在撰写本教程之际,已经有了最新的 RJB 版本)。

确保设置或更新了以下环境变量,它们是安装 RJB 所必需的:

  • JAVA_HOME 必须指向 Java SDK 安装目录。
  • PATH 必须包括 $JAVA_HOME/bin

例如,在 bash(仅用于 Linux 系统)中,假设已经将 Java SDK 安装到 /usr/local/jdk60,则执行以下命令:

[root@san]# export JAVA_HOME=/usr/local/jdk60
[root@san]# export PATH=$PATH:$JAVA_HOME/bin


编译和安装 RJB

下一步是通过执行以下命令编译和安装 RJB:

[root@san]# unzip rjb-1.1.3.zip
[root@san]# cd rjb-1.1.3
[root@san]# ruby setup.rb config
[root@san]# ruby setup.rb setup
[root@san]# ruby setup.rb install


确认安装成功

为了确认 RJB 安装成功,首先调用 Ruby 的交互式控制台 irb

[root@san]# irb


然后输入 require 'rjb'

irb(main):001:0> require 'rjb'
=> true
irb(main):002:0>exit


如果 require 'rjb' 命令返回 true,则意味着 Ruby 安装识别出新安装的 rjb 库。现在可以在应用程序中开始使用 RJB。

通过 RJB 使用遗留代码

在本节中,您将在 Rails 应用程序中装载和访问遗留 Java 代码。

示例项目

Java Tar package from ICE Engineering 是用 Java 语言编写的一个很好的工具包,用于处理归档文件。它提供了 tar 归档实用程序的本地 Java 实现,当与 java.util.zip 包相结合时,它可以处理 .tar.gz 文件。它还利用 Java 语言的平台独立性,可以不作修改地在所有 UNIX® 变体和 Windows 上运行。作为练习,您将使用它来解压一个样例 tar 文件的内容。通过类似的方法,可以在 Ruby on Rails 应用程序中使用任何遗留 Java 代码。

练习的目标是:

  1. 将 tar.jar 文件装载到一个 Rails 应用程序中。
  2. 将 JAR 文件所需的类装载到应用程序中。
  3. 解压使用这些类的样例 test.tar 文件的内容。

入门

获取样例文件

首先,需要为系统获取样例 tar 文件(test.tar)和 Java Tar 包:

  1. 将 test.tar 下载并保存 到一个方便的位置。
  2. 下载和保存 javatar-2.5.tar.gz。
  3. 将 javatar-2.5.tar.gz 的内容解压到一个方便的位置。这个练习中,这个包中惟一需要用到的文件是 tar.jar,它在 jars 目录中。

访问共享库

RJB 使用 Java Native Interface (JNI) 实现它的功能。因此,它需要访问 JDK 安装中附带的一些共享对象文件(共享库)。您必须使用以下命令将这些文件的位置添加到 LD_LIBRARY_PATH 环境变量中:

[root@san]# export JAVA_HOME=/usr/local/jdk60
[root@san]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/i386
[root@san]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/i386/client


如果打算在独立的 Ruby 脚本中使用 RJB,那么只需在正在处理的 shell 中设置这些环境变量。对于您的 Ruby on Rails 应用程序,还必须在 Rails 应用程序的 environment.rb 文件中设置这些变量

将 RJB 装载到 Rails 应用程序

要将 RJB 装载到 Rails 应用程序并将它设置为可以调用 Java 类,需要执行两个步骤:

  1. 告诉 Ruby 将 rjb 库包含到代码中。
  2. 装载 JVM,设置类路径和其他可选的 JVM 参数。

首先,使用下面的命令初始化 RJB:

require 'rjb'


接着,将 Rails 应用程序中将要使用的所有 legacy .jar 文件 — 本例中为 tar.jar — 添加到 classpath 变量:

Rjb::load(classpath = '.:/path/to/tar.jar', jvmargs=[])


可以将 jvmargs 留空,除非希望为 JVM 指定额外的参数。

现在,可以将准备使用的 Java 类导入到 Ruby 中,实例化这些类,并调用所需的方法。

将 Java 类导入到 Ruby 并实例化

清单 1 中的 Ruby 代码从 tar.jar 包中导入了需要的 Java 类,并从导入的类中创建了 Ruby 对象:

清单 1. 将 Java 类导入到 Ruby 并实例化
tararchive = Rjb::import('com.ice.tar.TarArchive')
fileinputstream = Rjb::import('java.io.FileInputStream')
file = Rjb::import('java.io.File')
file_instance = file.new_with_sig('Ljava.lang.String;','.')
fileinputstream_instance =
fileinputstream.new_with_sig('Ljava.lang.String;','test.tar')
tararchive_instance =
tararchive.new_with_sig('Ljava.io.InputStream;',fileinputstream_instance)
p "Let's verify that the objects created are indeed of the classes we
wanted..."
p "------------------------------"
p "For the File instance...."
p "Expecting: java.io.File , it is: " + file_instance._classname
p "------------------------------"
p "For the FileInputStream instance...."
p "Expecting: java.io.FileInputStream , it is: " +
fileinputstream_instance._classname
p "------------------------------"
p "For the TarArchive instance...."
p "Expecting: com.ice.tar.TarArchive , it is: " +
tararchive_instance._classname


导入 Java 类

清单 1 中的前三行将调用 RJB 的 import 方法,将所需的类分别导入到 Ruby 变量 tararchivefileinputstreamfile中。必须指定类的完整包路径 — 例如,TarArchive 类为 com.ice.tar.TarArchive,而 FileInputStream 类为 java.io.FileInputStream— 就像使用 java 命令运行应用程序那样。

实例化导入的类

接着,清单 1 创建导入类的对象。可以通过调用每个类的 new 方法创建类,就像创建任何 Ruby 对象一样(例如,tararchive.new)。但是这样做会调用 TarArchive 类的默认的构造函数(没有参数),而您并不希望这样做。

当重载了类的构造函数后,需要对上面的对象创建方法进行一些修改。在这种情况下,必须按照下面的方式创建对象:

object = Classname.new_with_sig('signature', parameter[,more parameters])


第一个参数定义构造函数所需的参数的签名类型。它告诉 RJB 调用其输入参数匹配指定签名的构造函数。

清单 1 中的第 4 个和第 5 个语句分别创建 filefileinputstream 类的对象,它们调用相应的构造函数,参数类型为 String

在清单 1 的第 6 个语句中,TarArchive 类的其中一个构造函数接受 InputStream 类型的对象作为参数。该语句的签名类型是一个单独的 InputStream 输入参数。这些类型签名的详细细节在 getName API 的 Java SDK 文档中做了很好的描述(参见 参考资料)。第二个参数是创建的 InputStream 类型对象。

检验对象创建

清单 1 中的其余内容将检验 RJB 创建的对象是否是指定类的对象,方法是调用添加到每个对象的 _classname 方法。例如,调用 tararchive_instance._classname 将返回 com.ice.tar.TarArchive,这意味着类被正确装载,并成功创建了该类的对象。

调用方法并捕获结果

将类装载到 Ruby 并从中创建了对象后,下一步是调用需要的方法并查看结果。例如,您希望使用 TarArchive 类的 extractContents 方法,将样例文件(test.tar)的内容提取到当前目录中。

和构造函数一样,可以使用两种方式调用方法。一种方式是直接调用方法,例如:

tararchive_instance.extractContents(file_instance)


当方法重载后,使用 _invoke 调用指定方法的每个参数的类型签名:

tararchive_instance._invoke('extractContents', 'Ljava.io.File;', file_instance)


这一步可以使 RJB 知道在方法重载时应该调用哪些方法。

和对待普通 Ruby 代码一样,您将捕获对象方法返回的结果(如果有的话),并在自己的应用程序中使用结果。方法调用返回的结果被自动转换为相应的对象类型。您只需在对象内直接调用方法。

Java TarArchive 类中实现的功能现在可以用于您的 Ruby 代码。通过使用相同的方法,Java 代码中已实现的任何功能可以不加修改地在您的 Ruby 和 Rails 应用程序中重用。

完整的代码

清单 2 展示了本教程示例的完整 Ruby 代码(也可以通过 下载 获得):

清单 2. 完整的示例 Ruby 代码
# Include 'rjb' library into your application
require 'rjb'
# Load the JVM specifying the jar files to include and any other optional JVM arguments
Rjb::load(classpath = '.:/path/to/tar.jar', jvmargs=[])
# Import the classes you want to use into a Ruby variable
# specify the full package path to the classes.
tararchive = Rjb::import('com.ice.tar.TarArchive')
fileinputstream = Rjb::import('java.io.FileInputStream')
file = Rjb::import('java.io.File')
# Create objects of the classes. Use the new method directly or use 
# the 'new_with_sig' call to invoke overloaded constructors with arguments
# Directory you want to extract the files in this case, the current directory
file_instance = file.new_with_sig('Ljava.lang.String;','.')
# inputstream instance of the file to extract
fileinputstream_instance = fileinputstream.new_with_sig('Ljava.lang.String;','test.tar')
# tararchive instance of the file to be extracted.
tararchive_instance = tararchive.new_with_sig('Ljava.io.InputStream;'\
                  ,fileinputstream_instance)
# Invoke the method from the class and capture the results.
# Use either the direct call of the method,
# or the '_invoke' call to invoke overloaded methods.
p 'Extracting file.....'
tararchive_instance.extractContents(file_instance)


尝试这些代码,将清单 2 中的代码保存到一个文件中,并且扩展名为 .rb(或使用 下载 中的 rjb-javatar.rb),然后在 Ruby 解释程序中运行。

结束语

在全新的 Rails 应用程序中重用已有的遗留 Java 代码其实非常简单,方式如下:

  1. 安装 Java SDK 和 RJB。
  2. JAVA_HOMELD_LIBRARY_PATH 环境变量导出到您的 Rails 应用程序的 environment.rb 文件中。
  3. 在应用程序中包括 rjb 库。
  4. 通过指定希望使用的 JAR 文件,装载 RJB 和 JVM。
  5. 从希望使用的 JAR 文件中将类导入到 Ruby 变量并创建类的对象。
  6. 开始在 Rails 应用程序中使用刚刚创建的类,就像使用任何 Ruby 对象一样。

如果希望在 Rails 应用程序中重用已经使用 Java 代码实现的业务逻辑,RJB 非常有用,并且不需要使用 Ruby 重新实现。它同时提供了 Ruby on Rails 和 Java 编程的优点。

考虑替代方法

还可以使用一种称为 JRuby 的替代方法,它可以实现与 RJB 相同的目标。JRuby 是使用 Java 语言实现的完整的 Ruby 包,使 Ruby 能够运行在 JVM 之上(参见 参考资料)。使用 JRuby,您可以访问所有 Java 库。JRuby 要求安装特定于 JRuby 的 Ruby Gems,因为针对非 Java 的 Ruby 的普通 Ruby Gems 不能与 JRuby 兼容。

RJB 和 JRuby 各有优缺点。对于 JRuby,Ruby 全部在 JVM 之上运行,每个 Ruby 调用将经过 JVM,这将使执行变得非常缓慢。同样,如果已经设置了一个 Rails 应用程序,需要从头开始设置,以便 JRuby 访问 Java 代码。作为原生 Ruby 包,RJB 易于安装,并且可以在已有的 Rails 设置中使用。如果需要在您的 Rails 应用程序中快速调用一些 Java 代码片段,那么 RJB 是最好的选择。

整体而言,在 Rails 应用程序中重用遗留 Java 代码的能力非常有用。使用 Java 语言实现的设计和编写都非常良好的业务逻辑不会搁置不用,相反,可以在新的 Web 应用程序中继续发挥有用的功能。

相关文章
|
1月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
2月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
|
14天前
|
Java API 微服务
2025 年 Java 核心技术全面升级与实战应用详解
这份Java校招实操内容结合了最新技术趋势,涵盖核心技术、微服务架构、响应式编程、DevOps及前沿技术等六大模块。从函数式编程到Spring Cloud微服务,再到容器化与Kubernetes部署,帮助你掌握企业级开发技能。同时,提供AI集成、区块链实践和面试技巧,包括高频算法题与系统设计案例。通过学习这些内容,可应对90%以上的Java校招技术面试,并快速上手实际项目开发。资源链接:[点此获取](https://pan.quark.cn/s/14fcf913bae6)。
104 41
|
20天前
|
人工智能 前端开发 Java
Java 面试资料中相关代码使用方法与组件封装方法解析
这是一份详尽的Java面试资料代码指南,涵盖使用方法与组件封装技巧。内容包括环境准备(JDK 8+、Maven/Gradle)、核心类示例(问题管理、学习进度跟踪)、Web应用部署(Spring Boot、前端框架)、单元测试及API封装。通过问题库管理、数据访问组件、学习进度服务和REST接口等模块化设计,帮助开发者高效组织与复用功能,同时支持扩展如用户认证、AI推荐等功能。适用于Java核心技术学习与面试备考,提升编程与设计能力。资源链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
52 6
Java 面试资料中相关代码使用方法与组件封装方法解析
|
2月前
|
人工智能 IDE 开发工具
JetBrains RubyMine 2025.1 发布 - 最智能的 Ruby 与 Rails IDE
JetBrains RubyMine 2025.1 (macOS, Linux, Windows) - 最智能的 Ruby 与 Rails IDE
90 30
JetBrains RubyMine 2025.1 发布 - 最智能的 Ruby 与 Rails IDE
|
19天前
|
存储 安全 Java
现代应用场景中 Java 集合框架的核心技术与实践要点
本内容聚焦Java 17及最新技术趋势,通过实例解析Java集合框架的高级用法与性能优化。涵盖Record类简化数据模型、集合工厂方法创建不可变集合、HashMap初始容量调优、ConcurrentHashMap高效并发处理、Stream API复杂数据操作与并行流、TreeMap自定义排序等核心知识点。同时引入JMH微基准测试与VisualVM工具分析性能,总结现代集合框架最佳实践,如泛型使用、合适集合类型选择及线程安全策略。结合实际案例,助你深入掌握Java集合框架的高效应用与优化技巧。
41 4
|
15天前
|
人工智能 Java
Java中的反射机制:深入探索与应用
本文介绍了Java反射机制的基本概念、用途及其实现方式。反射机制允许程序在运行时动态获取类的属性和方法,并调用它们,适用于处理私有成员或权限受限的情况。文章详细讲解了`Class`类的功能,包括获取类的方法、属性、注解、构造器等信息,以及通过四种方式获取`Class`对象的示例代码。此外,还探讨了类加载器、继承关系判断、动态代理等高级内容,展示了如何在运行时创建接口实例并处理方法调用。文末提供了完整的代码示例以加深理解。
Java中的反射机制:深入探索与应用
|
16天前
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
61 1
|
21天前
|
前端开发 Java 数据库连接
Java 编程进阶实操之工具集整合应用指南
本文聚焦Java编程进阶实操,涵盖并发编程、性能优化及数据库操作优化等核心知识点,并结合Hutool、Postman、Git等实用工具,提供从理论到实践的学习路径。通过小型图书管理系统实战项目,详细解析技术选型与实现步骤,助力开发者掌握Spring Boot、MyBatis等框架应用。同时展望Java新特性与技术趋势,为职业发展奠定基础。资源链接:[点此获取](https://pan.quark.cn/s/14fcf913bae6)。
52 1
|
1月前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
268 8