文章目录
- 背景
- 引入子模块时exclude失效
- Gradle Docker plugin推荐
- Docker打包SpringBoot多模块项目
- gradle构建的jar包找不到main入口
背景
原有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}"])
}
总结:网上的东西最多只能作为参考,发现问题的本质在于思考,多踩坑,以后才能避免被坑,这是我开发当中遇到的。