JavaScript di Java

Posting JavaLobby Baru-baru ini 10 Ciri Terpakai yang Tidak Digunakan di Java sangat popular. Pada masa penulisan ini, ia adalah jawatan teratas dalam kategori Pautan Teratas DZone. Sebagai tambahan, balasan untuknya juga telah dihantar Terdapat banyak pemerhatian menarik mengenai ciri-ciri yang kurang digunakan di Java di kedua-dua catatan blog dan saya bersetuju dengan beberapa yang lain daripada yang lain. Namun, item yang benar-benar menarik perhatian saya adalah pernyataan bahawa Java SE 6 adalah salah satu ciri Java yang paling tidak digunakan.

Saya sangat seronok bekerja dengan Java SE 6 dan telah menulis atau menulis blog mengenai ciri Java SE 6 beberapa kali pada masa lalu. Dalam posting blog ini, saya bermaksud untuk menunjukkan sebagian kemampuan Java SE 6 untuk mengehos melaksanakan kod JavaScript.

Sebilangan besar pengembang Java dan pengembang JavaScript memahami bahawa selain empat huruf "JAVA," JavaScript dan Java memiliki persamaan yang sangat sedikit selain beberapa warisan seperti C. Namun, kadang-kadang berguna untuk menjalankan bahasa skrip dari dalam kod Java dan Java SE 6 memungkinkan ini.

Pakej javax.script diperkenalkan dengan Java SE 6 dan termasuk kelas, antarmuka, dan pengecualian yang diperiksa terkait dengan penggunaan mesin skrip dalam Java. Posting blog ini akan memfokuskan pada ScriptEngineFactory, ScriptEngineManager, ScriptEngine, dan ScriptException.

Salah satu perkara pertama yang mungkin ingin dilakukan ialah menentukan mesin skrip yang sudah tersedia. Coretan kod seterusnya menunjukkan betapa mudahnya ini dilakukan dengan Java SE 6.

final ScriptEngineManager manager = new ScriptEngineManager(); for (final ScriptEngineFactory scriptEngine : manager.getEngineFactories()) { System.out.println( scriptEngine.getEngineName() + " (" + scriptEngine.getEngineVersion() + ")" ); System.out.println( "\tLanguage: " + scriptEngine.getLanguageName() + "(" + scriptEngine.getLanguageVersion() + ")" ); System.out.println("\tCommon Names/Aliases: "); for (final String engineAlias : scriptEngine.getNames()) { System.out.println(engineAlias + " "); } } 

Kod yang ditunjukkan di atas menghasilkan output seperti yang ditunjukkan dalam tangkapan skrin seterusnya.

Seperti yang ditunjukkan oleh gambar ini, mesin Mozilla Rhino JavaScript disertakan dengan Sun's Java SE 6. Kami juga melihat beberapa "nama umum" yang dikaitkan dengan mesin tertentu ini. Mana-mana nama ini boleh digunakan untuk mencari enjin ini. Dalam contoh kemudian dalam catatan ini, saya akan menggunakan nama umum "js" untuk carian ini.

Contoh kod seterusnya akan memanfaatkan mesin Rhino JavaScript yang disediakan untuk melaksanakan beberapa kod JavaScript dari kod Java. Dalam kes ini, kita akan memanfaatkan fungsi JavaScript toExponential.

 /** * Write number in exponential form. * * @param numberToWriteInExponentialForm The number to be represented in * exponential form. * @param numberDecimalPlaces The number of decimal places to be used in the * exponential representation. */ public static void writeNumberAsExponential( final Number numberToWriteInExponentialForm, final int numberDecimalPlaces) { final ScriptEngine engine = manager.getEngineByName("js"); try { engine.put("inputNumber", numberToWriteInExponentialForm); engine.put("decimalPlaces", numberDecimalPlaces); engine.eval("var outputNumber = inputNumber.toExponential(decimalPlaces);"); final String exponentialNumber = (String) engine.get("outputNumber"); System.out.println("Number: " + exponentialNumber); } catch (ScriptException scriptException) { LOGGER.severe( "ScriptException encountered trying to write exponential: " + scriptException.toString()); } } 

Kod di atas secara langsung meminta JavaScript menggunakan kaedah ScriptEngine.eval (String) untuk menilai String yang disediakan yang mengandungi sintaks JavaScript. Sebelum menggunakan evalkaedah, dua parameter "diteruskan" (terikat) ke kod JavaScript melalui panggilan ScriptEngine.put (String, Object). Objek hasil dari JavaScript yang dieksekusi diakses dalam kode Java menggunakan panggilan ScriptEngine.get (String).

Untuk menunjukkan kod di atas menggunakan toExponentialfungsi, saya akan menggunakan kod "pelanggan" berikut.

final int sourceNumber = 675456; writeNumberAsExponential(sourceNumber, 1, System.out); writeNumberAsExponential(sourceNumber, 2, System.out); writeNumberAsExponential(sourceNumber, 3, System.out); writeNumberAsExponential(sourceNumber, 4, System.out); writeNumberAsExponential(sourceNumber, 5, System.out); 

Apabila kod di atas dijalankan terhadap kaedah writeNumberAsExponential yang ditunjukkan sebelumnya dan JavaScript digunakan, outputnya kelihatan serupa dengan yang ditunjukkan dalam snapshot skrin seterusnya.

Contoh ini cukup untuk menunjukkan betapa mudahnya penggunaan fungsi JavaScript dari dalam Java SE 6. Namun, ini dapat dilaksanakan secara lebih umum seperti yang ditunjukkan oleh dua contoh berikutnya. Contoh pertama menunjukkan pemakaian JavaScript yang agak sewenang-wenang tanpa parameter dilewatkan / terikat dan contoh yang kedua menunjukkan pemakaian JavaScript yang agak sewenang-wenang dengan parameter yang dilalui / terikat.

Rentetan JavaScript yang agak sewenang-wenang dapat diproses dengan kod yang serupa dengan yang ditunjukkan seterusnya.

 /** * Process the passed-in JavaScript script that should include an assignment * to a variable with the name prescribed by the provided nameOfOutput and * may include parameters prescribed by inputParameters. * * @param javaScriptCodeToProcess The String containing JavaScript code to * be evaluated. This String is not checked for any type of validity and * might possibly lead to the throwing of a ScriptException, which would * be logged. * @param nameOfOutput The name of the output variable associated with the * provided JavaScript script. * @param inputParameters Optional map of parameter names to parameter values * that might be employed in the provided JavaScript script. This map * may be null if no input parameters are expected in the script. */ public static Object processArbitraryJavaScript( final String javaScriptCodeToProcess, final String nameOfOutput, final Map inputParameters) { Object result = null; final ScriptEngine engine = manager.getEngineByName("js"); try { if (inputParameters != null) { for (final Map.Entry parameter : inputParameters.entrySet()) { engine.put(parameter.getKey(), parameter.getValue()); } } engine.eval(javaScriptCodeToProcess); result = engine.get(nameOfOutput); } catch (ScriptException scriptException) { LOGGER.severe( "ScriptException encountered trying to write arbitrary JavaScript '" + javaScriptCodeToProcess + "': " + scriptException.toString()); } return result; } 

Kod di atas memberikan sedikit kelonggaran dari segi JavaScript yang dapat diproses. Ini mungkin bukan idea terbaik untuk kod pengeluaran, tetapi menjadikannya lebih mudah untuk menunjukkan penggunaan pelbagai ciri JavaScript di Java.

Contoh pertama untuk menggunakan pemprosesan JavaScript yang agak sewenang-wenang ini memanfaatkan objek Tarikh JavaScript. Contoh kod ditunjukkan seterusnya.

 System.out.println( "Today's Date: " + processArbitraryJavaScript( "var date = new Date(); var month = (date.getMonth()+1).toFixed(0)", "month", null) + "/" + processArbitraryJavaScript( "var date = new Date(); var day = date.getDate().toFixed(0)", "day", null) + "/" + processArbitraryJavaScript( "var date = new Date(); var year = date.getFullYear().toFixed(0)", "year", null) ); 

Kod ini menetapkan bahawa Tarikh JavaScript harus diambil (yang akan menjadi tarikh semasa) dan bulan itu, tarikh bulan, dan tahun penuh harus diekstrak dari Tarikh tersebut. Keluaran untuk ini muncul seterusnya.

Contoh terakhir bekerja pada String JavaScript sewenang-wenangnya tetapi tidak menggunakan parameter apa pun. Contoh berikutnya menunjukkan penyediaan parameter untuk pemrosesan String JavaScript sewenang-wenang ini kerana menunjukkan penggunaan fungsi pow JavaScript. Kod untuk contoh ini disenaraikan seterusnya.

 final Map exponentParameters = new HashMap(); exponentParameters.put("base", 2); exponentParameters.put("exponent", 5); System.out.println( "2 to the 5 is: " + processArbitraryJavaScript( "var answer = Math.pow(base,exponent)", "answer", exponentParameters) ); 

Hasil daripada menjalankan contoh ini ditunjukkan dalam tangkapan skrin berikut.

For my final example of this blog posting, I demonstrate the standard toString() output of the ScriptException declared in some of the previous examples. The ScriptEngine.eval method throws this checked exception if there is an error in executing/evaluating the provided script. This method also throws a NullPointerException if the provided String is null. The code used to force a script error is shown next.

 /** * Intentionally cause script handling error to show the type of information * that a ScriptException includes. */ public static void testScriptExceptionHandling() { System.out.println(processArbitraryJavaScript("Garbage In", "none", null)); } 

This code provides a nonsensical script (in terms of JavaScript syntax), but that is exactly what is needed to demonstrate the ScriptException.toString(), which is called as part of the exception handling in the method shown above for handling an arbitrary JavaScript String. When the code is executed, we see the exception information as shown in the next image.

Bahagian output yang berasal ScriptException.toString()adalah bahagian yang menyatakan: "javax.script.ScriptException: sun.org.mozilla.javascript.internal.EvaluatorException: hilang; sebelum pernyataan (# 1) di nombor baris 1."

Yang ScriptExceptionmengandungi nama file, nombor baris, dan nombor kolum pengecualian, sangat membantu jika fail dengan kod JavaScript disediakan untuk penilaian.

Kesimpulannya

Java SE 6 mempermudah penggunaan JavaScript dalam kod Java. Enjin skrip lain juga dapat dikaitkan dengan Java, tetapi sangat berguna untuk menyediakannya dengan Mozilla Rhino.

Gambaran Keseluruhan Kod dan Skrin Keluaran

Untuk kesempurnaan, saya memasukkan senarai kod lengkap di satu tempat di sini dan hasil yang dihasilkan selepas itu.

JavaScriptInJavaExample.java