利用Gradle如何构建scala多模块工程的步骤详解
前言
Scala是一门强大的语言,受到很多人的喜爱,我也曾经尝试学习过。不过Scala官网专用的构建工具SBT就不那么好用了。我曾经想将SBT的软件包保存路径设置到D盘,还想设置网络代理,不过最后都没搞明白怎么回事。相信也有很多同学想学习Scala,但是却被SBT挡在了门外。偶然之下我发现现在Gradle增加了scala插件,可以完美支持Scala项目。
前段时间终于无法忍受sbt慢如龟速的编译打包速度了。稍稍调研了一下,就果断切换到了gradle。由于调研得比较匆忙,在使用过程中遇到了各种问题。好在最后都能解决了。
我这里使用scala主要是用来编写spark job。由于我自己的一些需要,这些job中有几个是多模块的。在这里简单解释一下如何使用gradle构建scala多模块项目。
这里用我最近开发的项目来做说明。项目名称是consumer-portrait-job,有两个子模块:common和compute。
步骤如下
首先在项目根目录下创建一个settings.gradle文件,这个文件主要用来描述项目名称及子模块信息:
rootProject.name = 'consumer-portrait-job' include 'common', 'compute'
然后再创建一个build.gradle文件。这个文件描述了主项目及子项目的一些通用配置。配置如下:
allprojects { apply plugin: 'idea' group = 'com.zhyea.portrait' version = '0.1-SNAPSHOT' } subprojects { apply plugin: 'scala' sourceCompatibility = 1.7 targetCompatibility = 1.7 ext { scalaVersion = '2.10.5' sparkVersion = '1.4.1' } repositories { mavenLocal() maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } mavenCentral() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compileOnly group: 'org.apache.spark', name: 'spark-core_2.10', version: sparkVersion compileOnly group: 'org.scala-lang', name: 'scala-compiler', version: scalaVersion } task mkdirs() { sourceSets*.scala.srcDirs*.each { it.mkdirs() } sourceSets*.resources.srcDirs*.each { it.mkdirs() } } }
在这个配置文件中包含两个大的模块:allprojects和subprojects。
allprojects中的配置是所有项目共享的(包含根项目)。在这里,我定义了项目的groupId和version等信息,并应用了gradle的idea插件。
subprojects的配置是所有子项目通用的。
在subprojects中的第一行声明了使用gradle的scala插件。
接下来的配置项“sourceCompatibility”声明了编译时使用的jdk版本;“targetCompatibility”确保了编译生成的class与指定版本的jdk兼容。
在ext中声明了子项目中可以使用的一些变量。我这里是声明了scala和spark的版本。
repositories项配置了当前项目可以使用的仓库。这里使用的第一个仓库是本机的maven库,第二库是ali提供的repository服务,第三个库是maven中央库。(曾经研究过如何让gradle和maven公用同一个本地仓库,不过最后也是不了了之)。
dependencies中声明了所有子模块都需要使用的依赖项。这里用到了scala库和spark库,这两个库只会在编译期用到,所以声明使用的依赖类型是compileOnly(这种依赖类型是gradle Java插件独有的,gradle scala插件继承自java插件,所以也可以使用)。
task mkdirs是一个自定义任务。在根项目配置完settings.gradle和build.gradle后,执行“gradle mkdirs”命令完成子模块目录的创建工作。
在两个子模块common和compute下创建build.gradle文件并做配置。
common模块的build.gradle配置详情:
project(':common') { dependencies { compile group: 'com.typesafe', name: 'config', version: '1.3.2' } }
这里只是声明了一下commons模块独有的依赖项。
compute模块是启动模块,在该模块中有spark任务的驱动类。该模块的build.gradle配置详情:
project(':compute') { dependencies { compile project(":common") compileOnly group: 'org.apache.spark', name: 'spark-sql_2.10', version: sparkVersion compile group: 'net.liftweb', name: 'lift-json_2.10', version: '2.6.3' } jar { archiveName = 'consumer-portrait.jar' } task zip(type: Zip) { into('lib') { from(configurations.runtime) { include '*typesafe*', '*common*', '*bitmap-core*', '*RoaringBitmap*' } } into('') { from jar from 'doc' } } }
配置中的第一行dependencies仍然是配置compute模块的依赖项。其中略需注意的是对common模块的依赖。
接下来的jar声明指明了将该模块打成的jar包的名称。脚本中需要根据包名来调用模块生成的包,默认生成的包名会带上版本信息,不太合适。
最后是一个自定义任务。该任务的目标是将一些必要的jar和其他文件打成一个zip包,以便于上传任务到执行服务器。任务中的第一个部分是将一些运行时依赖打入zip包中的lib目录,使用include关键字提示包含运行时依赖中指定名称的包,也可以使用exclude关键字排除一些包。第二部分是将生成的jar和本地doc目录中的文件打入zip包的根目录。
就这样。有空再写个示例项目留着参考。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
- 从用户行为去理解内容-item2vec及其应用
- Dubbo与Zookeeper、SpringMVC整合和使用(入门级)
- Websocket HandShake Sec-WebSocket-Accept 生成策略
- 关于JVM CPU资源占用过高的问题排查
- ActiveMQ简单介绍以及安装
- Java Process destroy方法kill进程,返回码测试
- 百度人脸识别API Java调用
- Java Socket Timeout总结
- 求一个数组中子数组的最大和算法(Java实现)
- JDBC批量提交SQL的几点问题解答
- 工具推荐: 汽车CAN总线分析框架CANToolz
- Windows下jps, jconsole无法查看本地java进程问题解决
- DateFormat 线程不安全
- zip文件操作导致JVM crash
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【Rust日报】2020-08-07 无船同志关于Rust未来Generator语法的新尝试
- 11-2 环境是如何建立的
- 11-3 激活修改
- 12-1 定制提示符
- MySQL INSERT的4种形态
- PowerBI DAX 性能优化 高级视图算法 超越经典 性能提升成千上万倍
- Java开发必备 Git 分支开发:规范指南及完全学会Git的24堂课笔记
- 聊聊dubbo-go的failbackCluster
- 视频综合管理平台EasyNVS通道列表如何获得RTMP地址和RTSP地址?
- 【每周一库】 rust-ftp - an FTP client written in Rust
- Mall 电商实战项目发布重大更新,全面支持SpringBoot 2.3.0 !
- Python与Tableau相结合,万字长文搞定传统线下连锁店数据分析
- 社群答疑精选03:拆分数据到新工作表
- 【Rust日报】2020-08-08:用rust制作的一个Taskwarrior终端用户界面
- 【Rust日报】2020-08-09:1Paasword Linux版本