Java 相關(guān)工具
gradle
Overview
gradle 是一款基于JVM 的自動化構(gòu)建工具行拢。
gradle.build
文件是gradle 的配置文件,?其使用groovy 來構(gòu)建DSL 腳本挎塌。
在gradle 中, 有兩個基本概念:
- 項目是構(gòu)建產(chǎn)物(如jar 包)或?qū)嵤┊a(chǎn)物(將應(yīng)用程序部署到生成環(huán)境),一個項目包含若干個任務(wù)宝鼓。
- 任務(wù)是指不可分割的最小工作單元也搓,任務(wù)用來執(zhí)行真正的構(gòu)建工作赏廓。
在gradle 中,所有的特性都是由gradle 插件提供的傍妒, gradle 本身只提供了DSL 語言幔摸。
Usage
-
應(yīng)用gradle 插件:
apply plugin: 'java'
-
定義變量:
project.ext { guavaVersion = '18.0' ... }
-
定義依賴:
project.dependencies { compile(...) runtime(...) testCompile(...) }
-
定義任務(wù):
task uberjar(type: Jar, dependsOn: jar) {...}
Tips
-
由于gradle 的各個版本間存在兼容性問題,使用wrapper 讓每個項目的構(gòu)建環(huán)境獨立颤练。
在build.gradle 文件中使用以下的配置來指定本項目使用的gradle 半版本信息:
task wrapper(type: Wrapper) { gradleVersion = '2.5' }
gradle的項目構(gòu)建過程分為三個步驟:初始化既忆, 配置和執(zhí)行任務(wù)。使用
org.gradle.daemon=true
來啟動后臺進程來在構(gòu)建過程中跳過初始化步驟嗦玖,從而加速gradle 的構(gòu)建執(zhí)行尿贫。-
將項目拆分為多個子項目,可以利用gradle 提供的并行構(gòu)建能力踏揣。
- 在root 項目中的
build.gradle
中定義公共變量庆亡,任務(wù)和依賴。 - 在root 項目中的
settings.gradle
中定義包含的子項目捞稿。 - 在各個子項目的
build.gradle
中定義各項目所需的變量又谋,任務(wù)和依賴。
- 在root 項目中的
-
從cvs 中新獲取的項目后娱局,在命令行中依次執(zhí)行以下的命令:
>> gradle wrapper >> ./gradlew clean idea >> ./gradlew clean check
如果
check
任務(wù)通過彰亥,說明項目已經(jīng)在本地成功構(gòu)建。
Nexus
Overview
nexus是一款支持多種流行組件(如Maven衰齐,Docker 等)的倉庫管理軟件任斋。
在nexus 中,有兩個核心的概念:
-
component:一種資源耻涛,例如
library
或者framework
废酷。作為應(yīng)用程序的一部分,component 可以在運行時抹缕,集成澈蟆,單元測試執(zhí)行,或者在構(gòu)建過程中被引用卓研。在
build.gradle
中的表現(xiàn)為:project.dependencies { compile(...) runtime(...) testCompile(...) }
component 通常又被稱為artifact, package, bundle, achive 等趴俘。
-
repository:為了方便components 的使用睹簇,repository 聚合了components 集合,并在internet 上提供service寥闪。
- 組件通常有不同的格式太惠,例如maven repository 依賴于特殊的目錄結(jié)構(gòu)和XML 格式的元數(shù)據(jù), 并通過plain HTTP 命令和附帶的XML 文件來對component 進行交互疲憋。
Usage
-
指定從自建的nexus 倉庫中獲取依賴:
buildscript { repositories { jcenter() maven { url "your-nexus-repository-url" } } dependencies { classpath 'your-dependencies' } }
-
gradle upload
命令的上傳配置:project.uploadArchives { repositories { mavenDeployer { repository(url: "your-nexus-repository-url") { authentication(userName: "", password: "") } pom.version = "${project.version}" pom.artifactId = "${project.name}" pom.groupId = "${project.group}" } } }
Tips
-
本地緩存導(dǎo)致的依賴不及時刷新新版本:
configurations.all { resolutionStrategy.cacheChangingModulesFor 0, 'hours' }
* 根據(jù)版本號來分別存儲snapshot 和release 組件:
mavenDeployer {
repository(url: "your-nexus-repository-url" +
"${project.version.endsWith('-SNAPSHOT') ? 'snapshots' : 'releases'}") {...
?```
checkstyle
Overview
checkstyle 是一款Java 代碼風(fēng)格的檢查工具凿渊。
它是高度可配置化的,通過配置可以支持任意的代碼風(fēng)格(例如Sun Code Convensions 和Google Java Style)柜某。
checkstyle 的配置文件位于project/config/checkstyle/sun_checks.xml
。
通過修改該配置文件來統(tǒng)一項目的代碼風(fēng)格敛纲。例如喂击,出于源碼閱讀的考慮,想要限制代碼行的長度為100 個字符淤翔,則修改以下的配置:
<module name="LineLength">
<property name="max" value="100"/>
</module>
Usage
在項目的build.gradle
文件中翰绊,通過以下的配置使用checkstyle:
apply plugin: 'checkstyle'
checkstyle {
configFile = file("$project.projectDir/config/checkstyle/sun_checks.xml")
toolVersion = '6.7'
}
// 是否對測試代碼進行代碼風(fēng)格的檢查。
checkstyleTest {
enabled = false
}
Tips
- 不可變形參需要加上final.
- 將數(shù)字定義為有意義的
static final
常量(否則旁壮,會被認(rèn)為是magic number)监嗜。 - 在代碼提交前, 使用IDE 提供的format 快捷鍵抡谐, 過濾掉一些低級的風(fēng)格問題(如無用的引用裁奇, 代碼對其等等)。
findbugs
Overview
findbugs 是一款靜態(tài)檢查Java 代碼中bug 的工具麦撵。
在項目開發(fā)過程中刽肠,執(zhí)行gradle check
命令時,findbugs 會在coverageCheck
通過后執(zhí)行免胃。
如果代碼中含有工具認(rèn)為可能會引發(fā)Bug 的寫法音五,那么會在/yourProject/build/reports/findbugs
目錄中的生成一個main.xml
文件來記錄。
Usage
如果在check
過程中羔沙,出現(xiàn)了Execution failed for task ':findbugsMain'.
躺涝,那么打開main.xml
文件并找到以下的節(jié)點:
<BugInstance type="" priority="" rank="" abbrev="" category="">
根據(jù)type 字段,在網(wǎng)站中可以找到對應(yīng)的bug 的描述扼雏。
根據(jù)Class, Field, SouceLine
字段坚嗜, 可以在Java 源代碼中找到bug 對應(yīng)的源碼位置。
Tips
- 方法忽略了返回值(這常見于對不可變對象進行調(diào)用方法诗充,而誤以為不可變對象會被更新)惶傻。
- 忘記資源釋放(方法可能沒有關(guān)閉stream)。
- 在
switch-case
語句塊中缺少break
關(guān)鍵字其障。
jacoco
Overview
jacoco 是一款檢查代碼單元測試覆蓋率的工具银室。
jacoco 的配置文件位于config/scripts/coverage.gradle
。
如果代碼的覆蓋率沒有達到指定的標(biāo)準(zhǔn),那么會在yourproject/build/report/jacoco
目錄下生成index.html
和相關(guān)的結(jié)果文件蜈敢,打開該文件辜荠,可以看到圖形化顯示的沒有覆蓋到的代碼所在的文件和代碼位置。
Usage
- 在gradle 項目中抓狭,在該配置文件中定義jacoco 在gradle 的擴展和任務(wù):
project.extensions.create('coverage', CoverageExtension)
task coverageCheck(dependsOn: test) << {...}
- 在實際使用中伯病,我們定義了
excludePackages
和excludeClasses
對象來讓jacoco 跳過一些包和類的覆蓋率檢查。
coverage.excludePackages.each() {
exclude name: "${it.replaceAll('\\.', '/') + '/*'}"
}
coverage.excludeClasses.each() {
exclude name: "${it.replaceAll('\\.', '/') + '.class'}"
}
- 然后在
build.gradle
中使用以下的配置來在gradle check
任務(wù)中啟用jacoco 任務(wù)否过。
check.dependsOn "coverageCheck"
Tips
- 盡量使用TDD 的開發(fā)方式午笛。
- 在實際開發(fā)過程中,除了一些無法模擬的Exception 之外苗桂,盡量不要使用exclude 來跳過單元測試覆蓋率的檢查药磺。
flyway
Overview
flyway 是一款數(shù)據(jù)庫migration 工具。
相比于手動的sql 腳本的數(shù)據(jù)庫數(shù)據(jù)版本管理煤伟,數(shù)據(jù)庫migration 能夠帶來以下的優(yōu)勢:
- 從零開始重建一個數(shù)據(jù)庫癌佩。
- 清晰地獲知當(dāng)期數(shù)據(jù)庫狀態(tài)。
- 從當(dāng)前版本到任意的一個新狀態(tài)便锨。
flyway 使用schema_version 數(shù)據(jù)表管理數(shù)據(jù)庫的數(shù)據(jù)版本围辙。
Usage
-
在build.gradle 中進行以下的配置:
apply plugin: "org.flywaydb.flyway" flyway { url = 'your-database-schema-url' user = '' password = '' }
在以下的位置中放置數(shù)據(jù)庫migration 腳本:
yourProject/src/main/resources/db.migration
數(shù)據(jù)庫migration 腳本的命名格式:
V1__Create_demo_table.sql
。 需要注意的是版本號后面是兩個下劃線放案。
Tips
-
在測試中自動化地進行
flywayClean
和flywayMigrate
:test.dependsOn "flywayClean" test.dependsOn "flywayMigrate"
- 數(shù)據(jù)schema 的更新原則是只增不刪姚建,例如要修改某個既存表的結(jié)構(gòu),那么在一個新建的migration 腳本中進行吱殉,而不用去修改該寄存表的創(chuàng)建腳本桥胞。