Java Language
Usando otros lenguajes de scripting en Java
Buscar..
Introducción
Java en sí mismo es un lenguaje extremadamente poderoso, pero su poder se puede extender aún más gracias a JSR223 (Solicitud de especificación de Java 223) que presenta un motor de script
Observaciones
La API de scripting de Java permite que los scripts externos interactúen con Java
La API de scripting puede permitir la interacción entre el script y java. Los lenguajes de scripting deben tener una implementación de Script Engine en el classpath.
Por defecto, JavaScript (también conocido como ECMAScript) es proporcionado por nashorn de forma predeterminada. Cada Script Engine tiene un contexto de script donde todas las variables, funciones y métodos se almacenan en enlaces. En ocasiones, es posible que desee utilizar varios contextos, ya que admiten la redirección de la salida a un Escritor con búfer y el error a otro.
Hay muchas otras bibliotecas de motor de script como Jython y JRuby. Mientras estén en la ruta de clase, puede evaluar el código.
Podemos usar enlaces para exponer variables en el script. Necesitamos varios enlaces en algunos casos, ya que la exposición de las variables al motor básicamente consiste en exponer las variables solo a ese motor, a veces es necesario exponer ciertas variables como el entorno del sistema y la ruta que es la misma para todos los motores del mismo tipo. En ese caso, requerimos un enlace que es un alcance global. Exponer las variables que lo exponen a todos los motores de script creados por el mismo EngineFactory
Evaluando un archivo javascript en modo de script de nashorn
public class JSEngine {
/*
* Note Nashorn is only available for Java-8 onwards
* You can use rhino from ScriptEngineManager.getEngineByName("js");
*/
ScriptEngine engine;
ScriptContext context;
public Bindings scope;
// Initialize the Engine from its factory in scripting mode
public JSEngine(){
engine = new NashornScriptEngineFactory().getScriptEngine("-scripting");
// Script context is an interface so we need an implementation of it
context = new SimpleScriptContext();
// Create bindings to expose variables into
scope = engine.createBindings();
}
// Clear the bindings to remove the previous variables
public void newBatch(){
scope.clear();
}
public void execute(String file){
try {
// Get a buffered reader for input
BufferedReader br = new BufferedReader(new FileReader(file));
// Evaluate code, with input as bufferdReader
engine.eval(br);
} catch (FileNotFoundException ex) {
Logger.getLogger(JSEngine.class.getName()).log(Level.SEVERE, null, ex);
} catch (ScriptException ex) {
// Script Exception is basically when there is an error in script
Logger.getLogger(JSEngine.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void eval(String code){
try {
// Engine.eval basically treats any string as a line of code and evaluates it, executes it
engine.eval(code);
} catch (ScriptException ex) {
// Script Exception is basically when there is an error in script
Logger.getLogger(JSEngine.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Apply the bindings to the context and set the engine's default context
public void startBatch(int SCP){
context.setBindings(scope, SCP);
engine.setContext(context);
}
// We use the invocable interface to access methods from the script
// Invocable is an optional interface, please check if your engine implements it
public Invocable invocable(){
return (Invocable)engine;
}
}
Ahora el método principal
public static void main(String[] args) {
JSEngine jse = new JSEngine();
// Create a new batch probably unecessary
jse.newBatch();
// Expose variable x into script with value of hello world
jse.scope.put("x", "hello world");
// Apply the bindings and start the batch
jse.startBatch(ScriptContext.ENGINE_SCOPE);
// Evaluate the code
jse.eval("print(x);");
}
Su salida debe ser similar a esta
hello world
Como se puede ver la variable expuesta x se ha impreso. Ahora probando con un archivo.
Aquí tenemos test.js
print(x);
function test(){
print("hello test.js:test");
}
test();
Y el método principal actualizado.
public static void main(String[] args) {
JSEngine jse = new JSEngine();
// Create a new batch probably unecessary
jse.newBatch();
// Expose variable x into script with value of hello world
jse.scope.put("x", "hello world");
// Apply the bindings and start the batch
jse.startBatch(ScriptContext.ENGINE_SCOPE);
// Evaluate the code
jse.execute("./test.js");
}
Suponiendo que test.js está en el mismo directorio que su aplicación, debería tener una salida similar a esta
hello world
hello test.js:test