Springboot+Gradle+Docker構建多模組專案
文章目錄
背景
原有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}"])
}
總結:網上的東西最多隻能作為參考,發現問題的本質在於思考,多踩坑,以後才能避免被坑,這是我開發當中遇到的。假如對你有幫助,請留下您寶貴的點贊。