专业的软件一般都会有自己的命令行工具,如mysql的client端,启动后就会有mysql> 提示符,然后可以输入sql语句并执行。python、spark也有同样的命令行工具。 大型的行业软件,有很多也会有自己的命令行工具,看上去都挺高大上的。其中spark就是用scala的REPL实现的。
REPL就是Read Eval Print Loop,一般翻译成交互式解析器,而我非专业的说法就是一个命令行工具。网上也有不少介绍spark的REPL原理,但是看上去都有点复杂,其实我们通过scala实现自己的命令行工具,非常简单。
下面就说一下实现步骤,还是用gradle做构建工具:
1. 设置build.gradle,需要引用scala-compiler库
group 'com.mycompany'version '1.0-SNAPSHOT'apply plugin: 'scala'sourceCompatibility = 1.8repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }}dependencies { compile group: 'org.scala-lang', name: 'scala-library', version: '2.12.7' compile group: 'org.scala-lang', name: 'scala-reflect', version: '2.12.7' compile group: 'org.scala-lang', name: 'scala-compiler', version: '2.12.7'}
2. 在src/main/scala目录下新建MyPrjLoop 类
1) 覆盖prompt,填什么提示符就是什么样子了
2) 覆盖printWelcome,这里填上自己喜欢的欢迎界面就行,就像spark的命令行工具启动时提示spark那样。如果不覆盖,会提示scala版本信息。
3) initCmd是自定义变量,需要时填上自定义scala语句。
4) 覆盖createInterpreter方法,inp.quietRun(initCmd)。Inp是核心,首先解析initCmd中的scala语句。启动后通过命令行读入的语句也会交给它解析。
class MyPrjLoop extends ILoop{ override def prompt: String = "==>" override def printWelcome(): Unit = { echo("") } private val initCmd = """ """ override def createInterpreter(): Unit = { super.createInterpreter intp.quietRun(initCmd) }}
3. 创建入口类Main的Object类
1) 创建settings实例,设置settings.usejavacp.value,使用java classpath。
2) 执行MyPrjLoop的process方法。
object Main extends App{ val settings = new Settings settings.usejavacp.value = true new MyPrjLoop().process(settings)}主要工作就这三步,这个基本的命令行工具已经完成了,下面只要打包就行了。通过idea的artifacts打包:
然后就是build了,生成myproject_main.jar,然后执行$ java -cp myproject_main.jar Main
执行效果:
println是scala自带的方法,下面我们增加一个自定义的方法:
4. 创建com.mycompany.myprj包,在这个包下创建city类。
定义list方法:
package com.mycompay.myprjobject city { val cityList = List("beijing