如何使用ScriptEngine调用函数或模块。
这是我的示例代码,编译正常,但在运行时它抛出异常scalaVersion:=“2.12.4”和sbt.version = 0.13.16,java是jdk1.8.0_131
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)
答案 0 :(得分:3)
我认为问题在于 Scala 脚本引擎实现Compilable
,而不是Invocable
,这就是您获得强制转换异常的原因。
在任何情况下,当您对编译结果致电eval
时,您的代码都会被执行,因此您无需通过Invocable
调用任何内容。
使用asInstanceOf
有点皱眉,所以以下更具惯用性。
试试这个:
import java.io.FileReader
import javax.script._
object DemoApp extends App {
// Get the Scala engine.
val engine = new ScriptEngineManager().getEngineByName("scala")
// See if the engine supports compilation.
val compilerEngine = engine match {
case c: Compilable => Some(c)
case _ => None
}
// If the engine supports compilation, compile and run the program.
val result = compilerEngine.map {ce =>
val reader = new FileReader("src/main/scala/Demo.sc")
ce.compile(reader).eval()
}
println(result.fold("Script not compilable")(_.toString))
}
或者,如果您只想让原始代码正常工作,那么您应该这样:
import java.io.FileReader
import javax.script._
object DemoApp extends App {
val engine = new ScriptEngineManager()
.getEngineByName("scala")
.asInstanceOf[ScriptEngine with Compilable]
val reader = new FileReader("src/main/scala/Demo.sc")
val result = engine.compile(reader).eval()
// Output the result
println(result.toString)
}
答案 1 :(得分:0)
在脚本中使用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
Convert.scala
object Convert {
def fun(): String = {
"I am from Converter:: fun"
}
}
Second.scala
object Second {
def fun(): String = {
"I am from Second::fun"
}
}
在build.sbt
中excludeFilter in unmanagedSourceDirectories := "src/main/scripts/*.scala"
现在从应用程序我可以向已编译的脚本actor发送消息,并从Scripipts接收已处理的值