JSR 223を使用したJavaのスクリプト-個人的な経験から20行のテンプレートエンジンを作成する例

この記事はJavaの開発者に捧げられています。Java開発者はこれまで、またはこれまでのところ、明るいアジャイルな未来に向かって前進しているだけです。 読者はJava、Javascriptに精通しており、JSR 223について聞いたことがあると思われます。



多くの場合、「XまたはYのどちらが良いか」というトピックについて議論する必要がありました。 以前は、Java / C ++のペアでしたが、現在はスクリプト言語に重点が移っています。



ちょうど先日、同僚と私は、お気に入りの言語(JavaまたはC ++)で、火、水、銅のパイプを通過し、すべてを実行できるように見える人に、これらすべての革新を教える価値があるかどうかについて議論していました。 価値があると思います。



あらゆる言語で書かれたエレガントなコードの例は非常に多くありますが、関数型言語で書かれた優れたコードほど記憶に残るものはありません。 毎日Javascriptを使用している人を驚かせるのは難しいでしょうが、純粋なJavaの支持者にとっては、「有害な」スクリプトの不純物がなければ、何かが啓示のように見えるかもしれません。 この証拠は、私が直面しなければならなかった簡単な例です。



私が取り組んでいる小さなJavaプロジェクトは、単純なSwingインターフェースを作成することです。これはWeb Startを介して配布する必要があります。 そして、ここでは、Javaだけでサーバーサイドの豊富な追加ライブラリ(apache commons、spring、freemarker)に慣れている人は、自分にとって難しい選択をする必要があります。単に「おいしい」クラスがあるか、自分で何かを書いてください。 経験上、2番目のパスを選択できるように見えますが、同時にプロジェクトの複雑さが大幅に増加します。



たとえば、かなり複雑なHTMLを生成するタスクを処理する必要がありました。 データはモデルから取得され、このように見えます。ここではVelocityまたはFreemarkerを使用できますが、ページを美しく描画するためだけに何百ものクラスをプロジェクトに追加するという考えは気にしませんでした。 一方で、パーサー自体を書くのは30分ではなく、テストも...停止しますが! しかし、Javascriptで記述するとどうなりますか? 幸いなことに、JavascriptはJREで実行するのが非常に簡単です。さらに、Java7では、Javascript 1.8を知っているJavascriptエンジンが含まれています。これは、多くのおいしい「グッズ」を意味します。 そして、私は試してみることにしました。



構文はJSPのように選択されます。<%%>はステートメントのコレクションで、<%=%>は式です。 テストには、jrunscriptスクリプトコンソールを使用しました。 アイデアは非常にシンプルで、JSPが行うことを完全に繰り返します。テンプレートから特定のコードまたは関数を生成し、実行すると完成したページが返されます。 テストテンプレートの最も単純な例:



js> var string = "Variable x is <% if ( 'undefined' == typeof x ) { %> undefined <%} else { %> <%= x %><%}%>"
      
      





このようなテンプレートを処理するには、split関数を使用してそれを壊すだけで十分です。



 js> string.split(/<%(.*?)%>/).forEach(function(x,i)print((i+1)+': '+x)) 1: Variable x is 2: if ( 'undefined' == typeof x ) { 3: undefined 4: } else { 5: 6: = x 7: 8: } 9:
      
      







forEach呼び出しは、配列をうまく印刷するためだけに必要でした。 ご覧のように、行は奇数であり、偶数です-それらの間の式。 そして、私たちは別のものを必要としません。今では、関数の本体を形成するのはこの配列からの技術の問題です。



 js> string.split(/<%(.*?)%>/).map(function(s,i) (i % 2 > ? (s[0] == '=' ? 'this.push(' + s.slice(1) + ');' : s) > : (s && 'this.push(' + uneval(s) + ');') > )).join('\n') this.push("Variable x is "); if ( 'undefined' == typeof x ) { this.push(" undefined "); } else { this.push(" "); this.push( x ); }
      
      







そして、私がこのすべてを始めたその瞬間。 関数ジェネレータを作成する必要があります。実際、テンプレートをコンパイルします。



 js> function compile(template) new Function(template.split(/<%(.*?)%>/).map(function(s,i) (i % 2 > ? (s[0] == '=' ? ['this.push(', ');'].join(s.slice(1)) : s) > : (s && ['this.push(', ');'].join(uneval(s))) > )).join('\n')) js> compiled = compile(string) function anonymous() { this.push("Variable x is "); if ("undefined" == typeof x) { this.push(" undefined "); } else { this.push(" "); this.push(x); } }
      
      







私たちの話は終わりに近づいています。経験豊富な読者は、プッシュ関数を使用して結果の行を配列に追加することをおそらく既に推測しているでしょう。

結果をテストするために残っています:



 js> var array = []; compiled.call(array); array.join('') Variable x is undefined js> x = 5 js> compiled.call(array = []); array.join('') Variable x is 5
      
      







使いやすく、テンプレートハンドラーの準備ができるように、コードを装飾する必要があります。



結論:Javascriptを使用してかなり強力なテンプレートハンドラーを作成するのに約30分かかりましたが、Javaを使用している間は、1日か1週間かかるかを言うのも難しいと感じています。 今週に関しては、これはもちろん冗談ですが、真実からそう遠くありません。



All Articles