如何使用Scala脚本引擎调用函数或模块

如何使用Scala脚本引擎调用函数或模块,scala,scriptengine,Scala,Scriptengine,如何使用ScriptEngine调用函数或模块 下面是我的示例代码,它编译得很好,但在运行时抛出异常scalaversation:=“2.12.4”和sbt.version=0.13.16,java是jdk1.8.0131 import java.io.FileReader import javax.script._ object DemoApp extends App { val engine: ScriptEngine with Compilable with javax.scri

如何使用ScriptEngine调用函数或模块

下面是我的示例代码,它编译得很好,但在运行时抛出异常scalaversation:=“2.12.4”和sbt.version=0.13.16,java是jdk1.8.0131

import java.io.FileReader
import javax.script._

object DemoApp extends App {
    val engine: ScriptEngine with Compilable with javax.script.Invocable  = new ScriptEngineManager()
    .getEngineByName("scala")
    .asInstanceOf[ScriptEngine with javax.script.Invocable with Compilable]
    val reader = new FileReader("src/main/scala/Demo.sc")
    engine.compile(reader).eval()
    val result = engine.invokeFunction("fun")
}
下面是Demo.sc

def fun: String = {
"Rerutn from Fun"
}
下面是运行时的异常

Exception in thread "main" java.lang.ClassCastException: scala.tools.nsc.interpreter.Scripted cannot be cast to javax.script.Invocable
at DemoApp$.delayedEndpoint$DemoApp$1(DemoApp.scala:13)
at DemoApp$delayedInit$body.apply(DemoApp.scala:5)
at scala.Function0.apply$mcV$sp(Function0.scala:34)
at scala.Function0.apply$mcV$sp$(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App.$anonfun$main$1$adapted(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:389)
at scala.App.main(App.scala:76)
at scala.App.main$(App.scala:74)
at DemoApp$.main(DemoApp.scala:5)
at DemoApp.main(DemoApp.scala)

我认为问题在于Scala脚本引擎实现的是
可编译的
,而不是
可调用的
,这就是为什么会出现强制转换异常

在任何情况下,当您对编译结果调用
eval
时,您的代码将被执行,因此您不需要通过
Invocable
调用任何东西

使用
作为
的替代有点不受欢迎,因此下面的内容更为惯用

试试这个:

导入java.io.FileReader
导入javax.script_
对象DemoApp扩展应用程序{
//获取Scala引擎。
val engine=new ScriptEngineManager().getEngineByName(“scala”)
//查看引擎是否支持编译。
val compilerEngine=引擎匹配{
案例c:可编译=>Some(c)
案例=>无
}
//如果引擎支持编译,则编译并运行程序。
val result=compilerEngine.map{ce=>
val reader=newfilereader(“src/main/scala/Demo.sc”)
ce.compile(reader.eval)()
}
println(result.fold(“脚本不可编译”)(u.toString))
}
或者,如果您只是想让原始代码正常工作,您应该这样做:

导入java.io.FileReader
导入javax.script_
对象DemoApp扩展应用程序{
val engine=new ScriptEngineManager()
.getEngineByName(“scala”)
.asInstanceOf[可编译的脚本引擎]
val reader=newfilereader(“src/main/scala/Demo.sc”)
val result=engine.compile(reader.eval())
//输出结果
println(result.toString)
}

在脚本中使用actor的变通方法-

主应用程序演示

class SampleActor extends Actor {
    implicit val log = Logging(context.system, this)
    def fun() = {
        val settings: Settings = new Settings
        settings.sourcepath.value = "src/main/scripts"
        settings.usejavacp.value = true
        settings.dependencyfile.value = "*.scala"
        val engine: Scripted = Scripted(new Scripted.Factory, settings)
        engine.getContext.setAttribute("context0",context,ScriptContext.ENGINE_SCOPE)

        val reader = new FileReader("src/main/scripts/ActorScript.scala")
        engine.eval("import akka.actor.ActorContext \n" +"val context1 = context0.asInstanceOf[ActorContext]")

        val compiledScript : CompiledScript = engine.compile(reader)
        val x = compiledScript.eval()
        x.asInstanceOf[ActorRef] ! "Arikuti"
        x.asInstanceOf[ActorRef] !  1
    }
    override def receive: Receive = {
        case x : String =>
          log.info("Receveid  from ScriptEngine: " +  x)
        case i : Int =>
          log.info("Receveid from ScriptEngine : " +  i)
    }

    override def preStart(): Unit = {
        super.preStart()
        fun()
      }
    }

object ActorDemo {
  def main(args: Array[String]): Unit = {
  val system = ActorSystem("clientAdapter")
  val x = system.actorOf(Props(classOf[SampleActor]),"Main")
}
}
下面3张纸条放在src/main/scripts中

ActorScript.scala

import akka.actor.{Actor, ActorRef, Props}
import akka.event.Logging


class ActorScript extends Actor {
implicit val log = Logging(context.system, this)

override def receive = {
case y : Int   =>
  log.info("Recevied from Main Int : " +  y.toString )
  log.info(Convert.fun())
  sender.tell(2,self)
case x : String =>
  log.info("Recevied from Main String " + x)
  log.info(Second.fun())
  sender.tell("Arikuti",self)
}
}

object ActorScript {
  def apply: ActorRef = {
    context1.actorOf(Props(new ActorScript),"ScriptActor")
  }
}

ActorScript.apply
转换为scala

object Convert {
  def fun(): String = {
    "I am from Converter:: fun"
  }
}
第二,斯卡拉

object Second {
  def fun(): String = {
    "I am from Second::fun"
  }
}
In build.sbt

excludeFilter in unmanagedSourceDirectories :=  "src/main/scripts/*.scala"

现在,从应用程序中,我可以向编译脚本参与者发送消息,并从Scripits接收处理后的值argument@JaganArikuti我认为如果使用Scala脚本引擎是不可能的,因为它没有实现
Invocable
。如果您使用nashorn脚本引擎(它处理JavaScript脚本而不是Scala),那么您既可以编译JavaScript脚本,也可以调用它们定义的方法。使用Scala脚本引擎,您所能做的就是解释Scala脚本,或者编译它们并计算结果。