Calling JavaScript methods in Java

Source: Internet
Author: User
Tags java se

We all know the scripting language is very flexible, when dealing with some problems Java implementation in more than 10 lines to write, with JS may be less than 10 lines to write, and very concise, then there is no elegant way to combine Java and scripting language, in Java SE6 (code Mustang), this will become a reality.

Mustang's scripting engine

JSR 233 designed a set of scripting language APIs for Java. This set of APIs provides an interface for invoking various scripting language engines in Java programs.

Any scripting language engine that implements this interface can be called in a Java program. A Mozilla Rhino-based JavaScript scripting engine was included in the release of Mustang, meaning that the javase6+ version can be invoked directly to execute JavaScript.

Mozilla Rhino

Rhino is an open source JavaScript implementation that is pure Java. His name comes from the cover of the O ' Reilly book on JavaScript, yes, that Rhino book ...

The Rhino project can be traced to 1997, when Netscape planned to develop a pure Java implementation of Navigator, which required a Java implementation of Javascript--javagator.

It is also the predecessor of Rhino. In the beginning, Rhino compiled JavaScript into Java's binary code, so it would have the best performance. Later, because of the problem of garbage collection in the way of compilation execution and the overhead of the compilation and loading process, which did not meet the needs of some projects, Rhino provided a way to interpret execution.

With the Rhino open source, more and more users are using rhino in their products, and more and more developers are involved in the development of rhino and make a great contribution. Now Rhino will be included in the Java SE release, and more Java developers will benefit from it.

Rhino offers the following features

    • Full support for JavaScript 1.5+
    • The ability to use JavaScript directly in Java
    • A JavaScript shell is used to run JavaScript scripts
    • A JavaScript compiler for compiling JavaScript into a Java binary file
Supported scripting languages

The dev.java.net can find the official scripting engine implementation project. This project is based on BSD License, which indicates that the use of these scripting engines will be very free.

Currently, the project has supported more than 20 scripting languages, including Groovy, JavaScript, Python, Ruby, and PHP. This support list will also continue to expand.

Basic usage in Java

The retrieval of the scripting engine in Mustang uses the Factory mode. First you need to instantiate a factory: Scriptenginemanager

ScriptEngineManager factory = new ScriptEngineManager();

Scriptenginemanager will find the available scripting engine in the Thread context ClassLoader Classpath based on the meta-inf of the jar file. It provides 3 ways to retrieve the scripting engine:

// create engine by nameScriptEngine engine = factory.getEngineByName ("JavaScript");// create engine by nameScriptEngine engine = factory.getEngineByExtension ("js");// create engine by nameScriptEngine engine = factory.getEngineByMimeType ("application/javascript");

The following code will print out all the scripting engines supported by the current JDK:

new ScriptEngineManager();for (ScriptEngineFactory available : factory.getEngineFactories()) {  System.out.println(available.getEngineName());  // 打印脚本具体名称信息  System.out.println(available.getNames());}

You can see [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript] the output, the description of the executable Js script

Execute JS Script

Don't say anything, all know what to do, to print a sentence HelloWorld say:

publicclass RunJavaScript {  publicstaticvoidmain(String[] args){    new ScriptEngineManager();    ScriptEngine engine = factory.getEngineByName ("JavaScript");    engine.eval("print(‘Hello World‘)");  }}

If your Js has a syntax error, it will throw an javax.script.ScriptException exception

What if we were to explain some of the more complex scripting languages, or would you like to change the script at run time? The scripting engine supports an overloaded Eval method that reads the required script from a reader, or gets the absolute path to the Js file, and reads it directly with its own load function:

scriptenginemanager factory = new  Scriptenginemanager (); ScriptEngine engine = Factory. getenginebyname  (); eval  (new  Reader ( "Helloworld.js" )); File File = new  file (main.. getclassloader  (). getresource  ( "Test.js" ). getfile  ()); engine. eval  (new  filereader (file)); String ScriptPath = Main. class . getclassloader  (). getresource  ( "Test.js" ). getpath  () engine. eval  ( "load ('"  + scriptpath + );  

Note here that the relative path in the FileReader is relative to who (where the JVM starts), you can use ClassLoader to read the file under SRC

The Java program will dynamically read the script file and interpret the execution, which means that you can modify the code in the Js file when the program is running, and you will get the result in real time.

For this simple Hello world script, IO operations will lose about 20% of performance (SE6, personal testing) than directly executing the script, but the flexibility he brings---the ability to dynamically change the code at run time, is exciting in some situations.

Finally, take a look at the complete test code:

Package Com.bfchengnuo.javascript;import javax.script.*;import java.io.FileNotFoundException;/*** Created by Frozen commitment Andy on 2017/12/30. */ Public classMain { Public Static void Main(string[] args)throwsScriptexception, Nosuchmethodexception, filenotfoundexception {Scriptenginemanager manager =NewScriptenginemanager (); System. out.println("scripting language engine supported by the current JDK:"); for(Scriptenginefactory Available:manager.getenginefactories()) {System. out.println(available.Getenginename()); System. out.println(available.GetNames()); } scriptengine engine = Manager.Getenginebyname("JavaScript");if(! (Engineinstanceofinvocable)) {System. out.println("Invoking methods is not supported.");return; } engine.Eval("Print (' Hello world ')"); Invocable INV = (invocable) engine;//File File = new file (Main.class.getClassLoader (). GetResource ("Test.js"). GetFile ());    //Engine.eval (new FileReader (file));String ScriptPath = Main.class.getClassLoader().GetResource("Test.js").GetPath(); Engine.Eval("Load ('"+ ScriptPath +"')");//Get ObjectsObject calculator = engine.Get("Calculator");intx =3;inty =4; Object Addresult = Inv.InvokeMethod(Calculator,"Add", x, y); Object Subresult = Inv.InvokeMethod(Calculator,"Subtract", x, y); Object Mulresult = Inv.InvokeMethod(Calculator,"Multiply", x, y); Object Divresult = Inv.InvokeMethod(Calculator,"Divide", x, y); System. out.println(Addresult); System. out.println(Subresult); System. out.println(Mulresult); System. out.println(Divresult); }}

The corresponding Js file:

varCalculator= {};Calculator.Add = function(N1,N2){ returnN1+N2};Calculator.Subtract = function(N1,N2){returnN1-N2};Calculator.Multiply = function(N1,N2){returnN1*N2};Calculator.Divide = function(N1,N2){returnN1/n2};
scripting language communication with Java

The Put method of ScriptEngine is used to map a Java object into a variable of a scripting language . Now there is a Java Class, and it has only one method:

publicclass HelloWorld {  "Hello World";  publicvoidsayHello(){    System.out.println(s);  }}

The next step is to let Js use this class! Or look at the most real code:

publicclass TestPut {  publicstaticvoidmainthrows ScriptException {    new ScriptEngineManager();    ScriptEngine engine = factory.getEngineByName("JavaScript");    newHelloWorld();    engine.put("script_hello", hello);    engine.eval("script_hello.sayHello()");  }}

First we instantiate a HelloWorld and then use the Put method to map this instance to the variable Script_hello of the scripting language. Then we can invoke the method of this instance in the eval () function in the same way as in a Java program.

Use Invokefunction to execute the Js function:

publicclass TestInv {  publicstaticvoidmainthrows Exception {    new ScriptEngineManager();    ScriptEngine engine = factory.getEngineByName("JavaScript");    "function say(first,second) { print(first +‘ ‘+ second); }";    engine.eval(script);    Invocable inv = (Invocable) engine;    inv.invokeFunction("say""Hello""Tony");  }}

Here, one of the two optional interfaces of ScriptEngine is used: Invocable,invocable indicates that the current engine can be called as a function.

Here we cast the engine to the invocable type and use the Invokefunction method to pass the parameters to the scripting engine. Invokefunction This method uses the definition of a mutable parameter, which can pass multiple arguments at once, and the return value of the scripting language as its return value.

The Invocable interface also has a method for getting an instance of Java Interface from an engine that takes a Java Interface type as a parameter and returns an instance of this Interface.

That means you can write all the implementations of a Java Interface completely in a scripting language! Then call directly using the returned implementation class to do it!

engine.eval(script);Invocable inv = (Invocable) engine;MaxMin maxMin = inv.getInterface(MaxMin.class);

Does it feel good?

Other

The other can also compile the JS, in JS call Java code, but feel little use, the most commonly used or Java call Js method

Reference

Https://www.ibm.com/developerworks/cn/java/j-lo-mustang-script/index.html

Https://www.w3cschool.cn/java/scripting-in-java-call-javascript-function.html

Calling JavaScript methods in Java

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.