背景
原有Springboot基於Maven構建的多模塊項目需要改爲Gradle版的多模塊項目,派我前去開荒.
閱讀前:請先對gradle有一定了解,概念什麼的我就不多說,直接進入主題!
首先,分享下maven轉gradle,gradle轉有互轉的語法,可把pom.xml或build.gradle文件單獨拉到一個文件下執行裝換命令。
Maven轉Gradle:
gradle init --type pom
Gradle裝Maven:
在build.gradle中增加以下內容(group,version可自行更改,artifactId默認爲目錄名稱)
apply plugin: 'java'
apply plugin: 'maven'
group = 'com.101tec'
version = '0.7-dev'
sourceCompatibility = 1.6
然後./gradle.build,成功後將在build\poms目錄下生成的pom-default.xml文件,把它複製到根目錄下,改名成pom.xml即可
好了後,便開始踩坑之旅了,途中參考了很多鏈接幫助,忘了一一記錄下來,如發現有侵權的,請聯繫我,我加上轉發處。
首先,模塊管理會在settings.gradle裏添加include,如:
rootProject.name = 'Main'
include 'sub1'
include 'sub2'
配置build.gradle構建文件,構建多模塊項目的兩種方式,一種是集中式的共享配置,一種是分散式的私有配置。
第一種是所有配置都配置在父模塊目錄下的build.gradle,簡便快捷,不過我採用了第二種。
各個模塊配置一個build.gradle。
首先,在父模塊的build.gradle中配置公共的屬性,如:
allprojects {
apply plugin: 'maven'
group = 'com.demo'
version = '2.0.0'
}
subprojects {
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenLocal()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
}
接着各個模塊之間配置自己的依賴包,首先我遇到第一個問題:
引入子模塊時exclude失效
依賴子模塊時,要排除子模塊中的某個jar包,如:
compile(group: 'com.alibaba', name: 'dubbo', version:'2.5.7') {
exclude(module: 'spring')
exclude(module: 'log4j')
}
上面的語法,針對外部jar包倒是沒問題,但是到了子模塊上,就排除不掉了,經過一番折騰,原來是要用下面這種語法:
compile(project(':project-impl')){
exclude(module: 'project-mybatis')
exclude(module: 'mysql-connector-java')
}
真是汗,去除個包還有語法限制。
接着,本地沒遇到什麼大坑了,成功跑了起來。而後,我又來部署測試環境了,首先先用Docker打包成鏡像:
Gradle Docker plugin推薦
-
se.transmode.gradle:gradle-docker:1.2
這裏不詳談,有很多文章描述,可查看掘金上的一篇: -
gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.19.2
我用的便是這個,首先將其引入
buildscript {
...
repositories {
maven {url "https://plugins.gradle.org/m2/"}
}
dependencies {
classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.19.2')
}
}
apply plugin: 'com.palantir.docker'
docker {
dockerfile file('Dockerfile') //DockerFile路徑
name "${project.group}/${jar.baseName}:${jar.version}"
files jar.archivePath
buildArgs(['JAR_FILE': "${jar.archiveName}"])
}
簡單介紹下上面docker{}裏面的參數:
name是鏡像名,可自己設置名
buildArgs是設置構建時的環境變量,使用${jar.archiveName}獲取構建完的jar包,將其賦值給JAR_FILE變量,在Dockerfile那邊便可引用,如:
FROM openjdk:8
MAINTAINER dashuai
WORKDIR /
ARG JAR_FILE
ADD ${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
Docker打包SpringBoot多模塊項目
引入Docker配置便完成了,接着來到測試服務器上構建鏡像。
服務器是Ubuntu系統的,先導入項目,進入根目錄。
-
構建項目
gradle build
-
包下載完後,在打包鏡像,切記在父模塊目錄下執行
gradle subProject:docker
看到構建成功,好開森。
結果docker-compose up一跑,竟然出現:
No main manifest attribute, in app.jar
gradle構建的jar包找不到main入口
這就氣了,鏡像都打好了,你跟我說找不到main,然後又只能乖乖的找解決方案:
剛開始,本來用:
apply plugin: 'application'
mainClassName='com.main'
是可以運行的,本地是可以運行的,接着我又在服務器上運行:
gradle subProject:run
也是可以運行的,那爲什麼會找不到main呢,接着我又google,加了下面的配置:
jar {
manifest {
attributes 'Main-Class': 'com.main'
attributes 'Class-Path': 'subProject.jar'
}
}
在構建鏡像,在啓動容器,誒,竟然啓動了,好開森,結果,有出現類找不到了。我去,這不科學啊!難道包沒導進去,我便打開/build/libs/subProject.jar,看到裏面只有一些項目文件,並沒有發現jar,我去,打包成鏡像沒jar怎麼運行,這是一想肯定是打jar包方式有問題,又去google。最終,還是讓我解決了(っ•̀ω•́)っ✎⁾⁾。
最終的build.gradle如下:
buildscript {
repositories {
maven {url "https://plugins.gradle.org/m2/"}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE")
classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.19.2')
}
}
apply plugin: 'com.palantir.docker'
apply plugin: 'application'
apply plugin: 'org.springframework.boot'
group='com'
version = '3.0.5'
mainClassName='com.main'
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
dependencies {
compile group: 'org.springframework.data', name: 'spring-data-redis', version: '2.0.6.RELEASE'
compile 'net.sourceforge.nekohtml:nekohtml:1.9.21'
compile(group: 'com.alibaba', name: 'dubbo', version:'2.5.7') {
exclude(module: 'spring')
exclude(module: 'log4j')
}
//zkclinet自帶zookeeper不過版本太低,自己設一個版本給他,另外兩個包都得exclude纔有效
// log4j在gradle上不能去除,否則會去引起連接zookeeper超時
compile(group: 'org.apache.zookeeper', name: 'zookeeper', version:'3.4.11') {
exclude(module: 'slf4j-log4j12')
}
compile ('com.github.sgroschupf:zkclient:0.1'){
exclude(module: 'slf4j-log4j12')
}
}
docker {
dockerfile file('Dockerfile') //DockerFile路徑
name "${project.group}/${jar.baseName}:${jar.version}"
files jar.archivePath
buildArgs(['JAR_FILE': "${jar.archiveName}"])
}
總結:網上的東西最多隻能作爲參考,發現問題的本質在於思考,多踩坑,以後才能避免被坑,這是我開發當中遇到的。假如對你有幫助,請留下您寶貴的點贊。
如果想嘗試使用該插件的話,可參考構建鏡像Demo,GitHub地址:
https://github.com/liaozihong/SpringBoot-Learning/tree/master/SpringBoot-Builder-Docker