使用 Vert.x 将 JavaScript 带入您的 Java 企业

无需离开 JVM 部署,即可使用 JavaScript 的强大功能刷新您的企业工具箱。
278 位读者喜欢这个。
3 text editor alternatives to Emacs and Vim

opensource.com

如果您是一名 Java 程序员,您很可能过去使用过 JavaScript,或者在不久的将来会使用。JavaScript 不仅是最流行(且有用)的编程语言之一,了解 JavaScript 的一些特性还可以帮助您构建下一个超级流行的 Web 应用程序。

服务器端的 JavaScript

在服务器上运行 JavaScript 的想法并不新鲜;事实上,在 1995 年 12 月,就在为浏览器发布 JavaScript 后不久,Netscape 就推出了该语言的实现,用于使用 Netscape Enterprise Server 进行服务器端脚本编写。微软也在 Internet Information Server 上采用了它,作为 JScript,这是 Netscape JavaScript 的逆向工程实现。

种子已经播下,但真正的繁荣发生在 2009 年,当时 Ryan Dahl 推出了 Node.js。Node 的成功不是基于语言,而是基于运行时本身。它引入了一个遵循反应式编程原则的单进程事件循环,并且可以像其他平台无法做到的那样进行扩展。

企业和 JVM

许多企业已将 Java 虚拟机 (JVM) 标准化为运行其关键业务应用程序的首选平台,并且在 JVM 上进行了大量投资,因此这些组织寻找基于 JVM 的 JavaScript 运行时是有道理的。

Eclipse Vert.x 是一个在 JVM 上运行的多语言反应式运行时。将 Eclipse Vert.x 与 JavaScript 一起使用与您对 Node.js 的期望没有太大区别。存在一些限制,例如 JVM JavaScript 引擎与 ES6 标准不完全兼容,并非所有 Node.js 包管理器 (npm) 模块都可以与它一起使用。但它仍然可以做有趣的事情。

为什么选择 Eclipse Vert.x?

在 JVM 中进行了大量投资并且不想切换到不同的运行时,这可能是企业对 Eclipse Vert.x 感兴趣的充分理由。但其他好处是它可以与任何现有的 Java 应用程序交互,并在 JVM 上提供最佳性能之一。

为了演示,让我们看看 Vert.x 如何与现有的业务规则管理系统一起工作。想象一下,我们的虚构企业有一个关键任务应用程序在 JBoss Drools 中运行。我们现在需要创建一个新的 Web 应用程序,它可以与这个遗留应用程序交互。

为了简单起见,假设我们现有的规则是一个简单的 Hello World

package drools

//list any import classes here.

//declare any global variables here

rule "Greetings"
    when
        greetingsReferenceObject: Greeting( message == "Hello World!" )
    then
        greetingsReferenceObject.greet();
    end

当这个引擎运行时,我们得到“Drools Hello World!”这没什么了不起,但让我们想象这是一个非常复杂的过程。

实现 Eclipse Vert.x JavaScript 项目

与任何其他 JavaScript 项目一样,我们将使用标准的 npm 命令来引导项目。以下是如何引导 drools-integration 项目并准备它以使用 Vert.x

# create an empty project directory
mkdir drools-integration
cd drools-integration

# create the initial package.json
npm init -y

# add a couple of dependencies
npm add vertx-scripts --save-dev
# You should see a tip like:
#Please add the following scripts to your 'package.json':
# "scripts": {
#   "postinstall": "vertx-scripts init",
#   "test": "vertx-scripts launcher test -t",
#   "start": "vertx-scripts launcher run",
#   "package": "vertx-scripts package"
# }

# add
npm add @vertx/web --save-prod

我们已经初始化了一个基本的项目,因此我们可以开始编写 JavaScript 代码。我们将从添加一个简单的 HTTP 服务器开始,该服务器公开一个简单的 API。每次向 URL http://localhost:8080/greetings 发出请求时,我们都应该在终端中看到现有 Drools 引擎的执行结果。

首先创建一个 index.js 文件。如果您使用的是 VisualStudio Code,明智的做法是在文件开头添加以下两行

/// <reference types="@vertx/core/runtime" />
/// @ts-check

这两行将启用完全支持并检查代码中的语法错误。它们不是必需的,但它们确实在开发阶段有所帮助。

接下来,添加简单的 HTTP 服务器。在 JVM 上运行与在 Node 上运行不完全相同,并且许多库将不可用。将 JVM 视为无头浏览器,在许多情况下,在浏览器中运行的代码可以在 JVM 上运行。这并不意味着我们不能拥有高性能的 HTTP 服务器;事实上,这正是 Vert.x 所做的。让我们开始编写我们的服务器

import { Router } from '@vertx/web';

// route all request based on the request path
const app = Router.router(vertx);

app.get('/greetings').handler(function (ctx) {
    // will invoke our existing drools engine here...
});

vertx
// create a HTTP server
.createHttpServer()
// on each request pass it to our APP
.requestHandler(function (req) {
    app.accept(req);
})
// listen on port 8080
.listen(8080);

代码并不复杂,应该是不言自明的,所以让我们专注于以 Drools 规则的形式与现有 JVM 代码和库的集成。由于 Drools 是一个基于 Java 的工具,我们应该使用 java 构建工具构建我们的应用程序。幸运的是,因为在幕后,vertx-scripts 将 JVM 位委托给 Apache Maven,所以我们的工作很容易。

mkdir -p src/main/java/drools
mkdir -p src/main/resources/drools

接下来,我们添加文件 src/main/resources/drools/rules.drl,内容如下

package drools

//list any import classes here.

//declare any global variables here

rule "Greetings"
    when
        greetingsReferenceObject: Greeting( message == "Hello World!" )
    then
        greetingsReferenceObject.greet();
    end

然后我们将添加文件 src/main/java/drools/Greeting.java,内容如下

package drools;

public interface Greeting {

  String getMessage();

  void greet();
}

最后,我们将添加辅助实用程序类 src/main/java/drools/DroolsHelper.java

package drools;

import org.drools.compiler.compiler.*;
import org.drools.core.*;
import java.io.*;

public final class DroolsHelper {

  /**
   * Simple factory to create a Drools WorkingMemory from the given `drl` file.
   */
  public static WorkingMemory load(String drl) throws IOException, DroolsParserException {
    PackageBuilder packageBuilder = new PackageBuilder();
    packageBuilder.addPackageFromDrl(new StringReader(drl));
    RuleBase ruleBase = RuleBaseFactory.newRuleBase();
    ruleBase.addPackage(packageBuilder.getPackage());
    return ruleBase.newStatefulSession();
  }

  /**
   * Simple factory to create a Greeting objects.
   */
  public static Greeting createGreeting(String message, Runnable andThen) {
    return new Greeting() {
      @Override
      public String getMessage() {
        return message;
      }

      @Override
      public void greet() {
        andThen.run();
      }
    };
  }
}

我们不能直接使用该文件;我们需要有 drools。为此,我们在名为 mvnDependenciespackage.json 中添加一个自定义属性(遵循通常的模式)

{
    "mvnDependencies": {
        "org.drools:drools-compiler": "6.0.1.Final"
    }
}

当然,由于我们更新了项目文件,我们应该更新 npm

npm install

我们现在进入这个项目的最后一步,我们将 Java 和 JavaScript 混合在一起。我们之前有一个占位符,所以让我们填补空白。我们首先使用辅助 Java 类创建一个引擎(您现在可以看到 Vert.x 的强大功能,一个真正的多语言运行时),然后在每次 HTTP 请求到达时调用我们的引擎。

// get a reference from Java to the JavaScript runtime
const DroolsHelper = Java.type('drools.DroolsHelper');
// get a drools engine instance
const engine = DroolsHelper.load(vertx.fileSystem().readFileBlocking("drools/rules.drl"));

app.get('/greetings').handler(function (ctx) {
  // create a greetings message
  var greeting = DroolsHelper.createGreeting('Hello World!', function () {
    // when a match happens you should see this message
    console.log('Greetings from Drools!');
  });

  // run the engine
  engine.insert(greeting);
  engine.fireAllRules();

  // complete the HTTP response
  ctx.response().end();
});

结论

正如这个简单的例子所示,Vert.x 允许您真正实现多语言。选择 Vert.x 的原因不是因为它只是另一个 JavaScript 运行时,而是一个运行时,它允许您重用已有的东西,并使用运行互联网的工具和语言快速构建新代码。我们在这里没有涉及性能(因为它本身就是一个话题),但我鼓励您查看独立的基准测试,例如 TechEmpower,以探索该主题。

评论已关闭。

© . All rights reserved.