Mozilla Rhinoを使用した簡単で動的なJavaScriptビジネスロジック

画像



背景



背景から始めたいと思います。 現時点では、ある種のJava Webアプリケーションを開発していますが、これは珍しいことではありませんが、ドキュメントには顧客からの要件があります。将来のアプリケーション管理者は、サーバーにビジネスロジックコードをオンザフライでロードできるはずです。 超自然的なことではないように思えますが、Javaクラスをロードする必要があると思います。最近まで、「JavaScriptでビジネスロジックメソッドをプログラミングする機会を与えたらどうなるでしょうか」という考えが浮かびました。

その瞬間、このアイデアは私にとって非常に良さそうに見え、Javaクラスの単純なロードを超えるこのアイデアの多くの利点を見ました。





しかし、大きな力は大きな責任であることを忘れないでください。そのため、新しい機会の後、詳細な答えを必要とする新しい質問が生じます。

この記事では、純粋なjsでビジネスロジックを記述するという考え方について簡単に説明し、理論的および実用的な部分に触れ、この決定後に生じる可能性のあるニュアンスのいくつかについて説明したいと思います。





JavaScriptインタープリターの選択



jsを解釈するエンジンに遅れをとる必要はありませんでした。最初の候補はMozilla Rhinoです-jsエンジンは完全にJavaで書かれています。

このエンジンは、1997年にNetscapeの壁に「Javagator」という名前で生まれましたが、その後、不思議な状況下でRhinoと改名されました。 Rhinoは、そのプロジェクトのためにいくつかの大企業(Sunを含む)によってライセンスされています。 最初は、JavaScriptに基づいてJavaバイトコードをコンパイルするというアイデアでしたが、このアプローチにはいくつかの問題がありました。





1998年に、デフォルトでインタープリターモードがエンジンに追加されました。 JavaScriptコードは、バイトコードへのコンパイルをバイパスして、オンザフライで実行されます。 これにより、大量のコンパイルやメモリリークの問題が回避されました。 今年後半、エンジンはソースコードを開き、mozilla.orgに提供されます。

ライブラリのバイナリとソースコードは、公式Webサイト(サイトへのリンク)からダウンロードできます。 例ではrhino1.7 R4を使用します。

Rhinoは2つの方法で使用できます。コマンドラインから使用する方法と、プロジェクトにjarファイルを埋め込む方法です。 ここで、まさに2番目の方法に興味があります-js.jarファイルをプロジェクトに追加します。



LiveConnectテクノロジー



Rhinoの主なアイデアの1つは、LiveConnectテクノロジーを使用してJavaScriptコードを使用してJavaサーバーをプログラムする機能です。 この技術により、サードパーティのコードに頼ることなく、jsからJavaクラスに直接アクセスできます。

File



クラスとSystem



クラスにアクセスする小さな例を次に示します。

 var f = new java.io.File(“test.txt”); java.lang.System.out.println(f.exists());
      
      





LiveConnectは、私たちに多くの行動の余地を与えてくれます。それについてはオフィスでたくさん書かれています。 エンジンのドキュメントですが、今は詳しく説明しません。 Javaクラスへのアクセス権を持たない信頼できない外部ソースからのコードの解釈に興味があります。



Rhinoを使用する



例として、大学の仮想プロジェクト「学生会計および学年会計サービス」のためのシンプルなビジネスロジックモジュールを開発します。 アプリケーションは、すべての生徒と成績のリストを保持し、タスクに基づいて生徒に対して何らかのアクションを実行できる必要があります。

使用の基本から始めましょう。 Rhinoには2つの主要な概念があります-これはコンテキスト(クラスorg.mozilla.javascript.Context



)とスコープ(クラスorg.mozilla.javascript.Scriptable



)です。 コンテキストは、単一のスレッドにバインドするインタープリターインスタンスであるため、単一のスレッドでjsを解釈します。 球体は、名前空間と呼ばれるもので、対象となるすべての変数を定義します。

コンテキストとスコープを作成する例:

 //   Context context = Context.enter(); //   Scriptable scope = context.initStandardObjects();
      
      





コンテキストとスコープを作成したら、Javaクラスへのインタープリターアクセスを制限する必要があります。 これは、 setClassShutter



インスタンスのsetClassShutter



メソッドを使用して行われます。

 //   LiveConnect  Java- context.setClassShutter(new ClassShutter() { @Override public boolean visibleToScripts(String fullClassName) { // ,      fullClassName  return false; } });
      
      





デフォルトでは、RhinoはLiveConnectテクノロジーを使用します。これにより、jsから直接Javaクラスにアクセスできます。 信頼できるコードに大きなチャンスを与えますが、別のケースがあります-サーバーは潜在的に安全でないコードを解釈します。

次の形式のjs-codeがインタープリターに入ると、非常に不快になります。

 java.lang.System.exit(0);
      
      





したがって、単にLiveConnectを「プラグ」し、必要なクラスへのアクセスのみを残します。 コンテキストとスコープを取得したら、jsコードを解釈する以外に方法はありません。

 String script = “var mathStuff = Math.cos(Math.PI)”; c.evaluateString(scope, script, null, 1, null);
      
      





Rhinoを使用した後、コンテキストの使用を終了し、リソースを解放します。

 Context.exit();
      
      







ビジネスロジック用の「サンドボックス」



Rhinoの使用を開始する方法がわかったので、次に、トップレベルモジュールへのいくつかの定数リンクの形式で外部ビジネスロジックAPIを定義することに進みます。





 public class DatabaseModule { public DatabaseModule(){ } /*    ,       */ public String getStudent(int id){ return (id > 0) ? "  " : null; } /*    ,       */ public int getRating(String student){ return student.equals("  ") ? 5 : -1; } /*     ,          */ public void setRating(String student, int newRating){ System.out.println("setRating() student = "+student+", newRating = "+newRating); // Do something } }
      
      





 public class NotificationModule { public NotificationModule(){ } /*     */ public void notifyStudent(String student, String message){ System.out.println("notifyStudent() student = "+student+", message = "+message); } /*    */ public void notifyCurator(String message){ System.out.println("notifyCurator() message = "+message); } }
      
      





次に、以前に定義した領域のモジュールへの定数リンクを定義します。

 //  DatabaseModule  js DatabaseModule database = new DatabaseModule(); Object wrappedDatabaseModule = Context.javaToJS(database, scope); ScriptableObject.putConstProperty(scope, "databaseModule", wrappedDatabaseModule); //  NotificationModule  js NotificationModule notification = new NotificationModule(); Object wrappedNotificationModule = Context.javaToJS(notification, scope); ScriptableObject.putConstProperty(scope, "notificationModule", wrappedNotificationModule);
      
      







JavaScriptビジネスロジックプログラミング



データベースから学生に関する情報を識別子で選択し、成績を取得し、試験に入学するのに十分なポイントがあるかどうかを計算し、学芸員と学生自身に通知するタスクがあるとします。 この場合、タスク全体がそのようなjs-codeに分類されます。

 var student = databaseModule.getStudent(1); var rating = databaseModule.getRating(student); var pass = rating >= 40; if(pass){ notificationModule.notifyCurator("Student "+student+" is admitted to the exam."); notificationModule.notifyStudent(student, "You admitted to the exam."); } else { var dif = 40 - rating; notificationModule.notifyCurator("Student "+student+" needs "+dif+" points to be admitted to the exam."); notificationModule.notifyStudent(student, "You need "+dif+" points to be admitted to the exam."); }
      
      





残っているのは、インタープリターを構成してjsを渡すことだけです。 すぐに警告します。エンジンはキリル文字を痛感します。



おわりに



結論として、jsでビジネスロジックをプログラミングするというアイデアは、新しいものではありませんが、非常に興味深いものです。 このアプローチは、柔軟性と実装の容易さを提供します。

新しいメソッドを追加するタスクに直面しているプログラマーは、サーバー側でどのテクノロジースタックが使用されているかを考える必要はなく、単に何をする必要があるかを規定し、機能を簡単に拡張および補完します。

このアプローチによって提供される機会に続いて、戦闘サーバーに実装する前に注意しなければならないいくつかの質問があります。





幸いなことに、すべての問題は完全に解決可能であり、Rhinoのソースコードは修正のために公開されています。



便利なリンク


の。 プロジェクトのウェブサイト: https : //developer.mozilla.org/en/docs/Rhino

ウィキペディアの記事: http : //en.wikipedia.org/wiki/Rhino

の。 ドキュメント: https : //developer.mozilla.org/en-US/docs/Rhino_documentation

APIリファレンス(ではない): Http : //tool.oschina.net/uploads/apidocs/rhino/

GitHubサンプルのソース: https : //github.com/andrew-medvedev/rhino-example



All Articles