如何使用Scala脚本引擎调用函数或模块
如何使用ScriptEngine调用函数或模块 下面是我的示例代码,它编译得很好,但在运行时抛出异常scalaversation:=“2.12.4”和sbt.version=0.13.16,java是jdk1.8.0131如何使用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
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脚本,或者编译它们并计算结果。