使用gradle构建springboot多模块项目,并构建成docker容器的demo

使用gradle构建springboot多模块项目,并构建成docker容器的demo.

基础环境

  • gradle(4+)
  • java(8+) PS:最好还是使用jdk8,因为9之后发生了一些变化,比如删除了一些包.
  • docker(可选)

构建过程

!!! 构建过程建立在已经安装了基础环境的条件之上.

1.创建项目根目录,此处项目名称为:java-springboot-gradle-docker

mkdir java-springboot-gradle-docker && cd java-springboot-gradle-docker

上面的命令将会创建一个java-springboot-gradle-docker目录,并进入该目录下,此处可以替换为自己想要的跟项目名称.

这里建立的目录,将会作为多模块项目的顶层项目存在.

2.初始化为gradle项目

gradle init

gradle的init任务,通常用来生成gradle项目的基础结构,可以通过type来指定生成gradle项目的类型,这里不指定的目的是为了完全自己一步步构造完整的目录结构.

在实际使用过程中可以根据自己的需要选择类型,比如java-application.

在不指定type的前提下,该命令将会在目录下生成以下基础文件:

    build.gradle
    gradle
    gradlew
    gradlew.bat
    settings.gradle

build.gradle是项目构建文件,也是接下来会主要修改的文件,我们将会通过修改该文件来实现插件和依赖的版本管理等功能.

gradle是一个目录,主要包含了gradle的包装器,他和gradlew,gradlew.bat文件一起,主要作用就是可以让用户在不安装gradle的情况下,
依然可以使用gradle提供的功能.

settings.gradle则主要用来在多模块的时候实现管理子模块的功能.

3.编写gradle.properties文件.

在跟项目目录下执行下列命令来生成gradle.properties文件.

echo "#Gradle资源文件
#指定当前项目的JDK(适用于不使用系统环境变量对应的JDK)
org.gradle.java.home=/usr/local/java8
#启用并行编译
org.gradle.parallel=true
#启用编译守护进程
org.gradle.daemon=true
#配置可用编译内存
org.gradle.jvmargs=-Xms256m -Xmx1024m">>gradle.properties

gradle.properties文件的主要作用是为gradle在运行期间提供一些参数,下面是这次使用的参数及其作用.

#Gradle资源文件
#指定当前项目的JDK(适用于不使用系统环境变量对应的JDK)
org.gradle.java.home=/usr/local/java8
#启用并行编译
org.gradle.parallel=true
#启用编译守护进程
org.gradle.daemon=true
#配置可用编译内存
org.gradle.jvmargs=-Xms256m -Xmx1024m

需要注意的是,上面的参数可以根据自己的需求来改变.

参数org.gradle.java.home参数,需要修改为自己的JAVA_HOME路径,否则将会报错.

如果当前已经配置了JAVA环境变量的话,可以将该配置注释掉.

4.创建一个新的目录,并修改其为一个子模块项目.

创建一个目录.这次创建的目录将会作为多模块的子模块项目出现,这里建立一个eureka-demo子模块.

mkdir eureka-demo

修改settings.gradle文件,将eureka-demo作为子模块.

echo "include 'eureka-demo'" >>settings.gradle

settings.gradle文件的include属性,定义了当前gradle项目包含的子模块,如果有多个子模块,可以使用多个include的形式来配置.

5.新建一个用户自定义参数的配置文件(可选).

这一步,并不是必须的,如果需要跳过这一步,可以将本来应该保存在该文件的数据,放到build.gradle中的buildscript代码块中即可.

在本项目中,不会使用到buildscript代码块,但是需要知道的是,buildscript代码块主要是用来声明gradle脚本本身需要使用的资源,而在其他地方直接声明的配置,
将会作用在项目中.

为了尽可能的将数据模块化,简洁化,所以这里新建一个文件用来存放依赖jar包的版本和一些通用的参数配置.

首先,在项目根目录下新建一个目录gradle(此时该目录应该是已经存在的,如果已经存在不需要新建).

mkdir gradle

进入gradle目录下,新建一个dependency.gradle文件,并输入以下内容:

/**
 * ===================================================================================================================
 * -------------------------------------------      统一资源版本控制       ----------------------------------------------
 * ===================================================================================================================
 */

def version = [
        JDK                    : JavaVersion.VERSION_1_8,           //JDK
]
//统一文件编码控制
def encoding = [
        OPTIONS: 'UTF-8'
]
//暴露参数
ext.custom = [
        version : version,
        encoding: encoding,
]

6.修改build.gradle文件,构建项目的公共配置.

因为接下来的操作涉及到的内容比较多,所以采用文本编辑器的形式来编辑(比如:vim).

接下来的步骤会在build.gradle文件插入大量的数据,如果找不到应该插入的位置,可以在本文的底部查看该实例项目的开源地址
,或者查看底部的完整配置文件内容.

我们首先删除掉build.gradle文件内的所有内容,因为其本身生成的文件内部只是添加了一个测试依赖而已,并不是必须的.

我们首先需要引入一些通用的插件.

所以在build.gradle文件中中输入下面的内容.

configure(allprojects) { project ->

  //项目基础属性
    group 'cn.jpanda'           //项目所属组织
    version '1.0-SNAPSHOT'      //项目版本号

    //引入插件
   apply plugin: 'java'                                            //java插件
   apply plugin: 'maven'                                           //maven插件
   apply plugin: 'idea'                                            //IDEA插件
   apply plugin: 'eclipse'                                         //eclipse插件
   apply from: "${rootProject.rootDir}/gradle/dependency.gradle"   //引入jar包版本配置文件

   //JDK版本声明
  sourceCompatibility = custom.version.JDK
  targetCompatibility = custom.version.JDK

  //配置仓库
 repositories {
     mavenLocal()
     maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
     maven { url 'https://repo.spring.io/libs-snapshot' }
     maven { url "https://repo.spring.io/snapshot" }
     maven { url "https://repo.spring.io/milestone" }
     mavenCentral()
     jcenter()
     maven {
         url "https://plugins.gradle.org/m2/"
     }
 }

 //指定项目编码
 tasks.withType(JavaCompile) {
     options.encoding = "${custom.encoding.OPTIONS}"
 }

}

configure(allprojects) { project ->}表示内部的配置将会应用于所有的项目,在下面还会出现configure(subprojects){},其表示
配置的数据将会应用在所有的子项目内,两者的区别主要就是allprojects和subprojects.

在这里主要进行了项目的一些公共配置,比如项目共用的插件以及仓库等配置.

上面没有涉及太多的东西,具体的代码作用已经标注上了注释.

7.添加gradle包装器(可选).

添加gradle wrapper可以统一开发使用gradle的版本,
避免在开发过程中因为gradle版本不一致而引发的问题.

在build.gradle文件的底部,加入代码:

/**
 * 生成gradlew文件,统一gradle版本,避免因为版本不同产生的问题
 */
task wrapper(type: Wrapper) {
    gradleVersion = "4.8"  //这里的版本根据自己的需求变更.
}

之后我们通过gradle wrapper命令就可以生成gradlew和gradlew.cmd文件了.

PS:虽然我们在执行gradle init的时候已经生成了该文件,但是默认生成的文件是我们自己电脑gradle版本的包装器,所以如果需要使用不同的版本,
最好还是执行这一步.

8.引入jar包依赖管理插件.

在使用maven进行构建的项目的时候,我们通常会使用dependencyManagement标签统一管理所有项目的依赖,来尽量避免jar包冲突的问题.

这里spring boot同样提供了org.springframework.boot插件
来在gradle中实现类似的功能.

引入该插件,需要在build.gradle中的开始部分输入以下内容:

plugins {
  id 'org.springframework.boot' version '2.0.1.RELEASE'           //spring提供的spring boot插件,主要用到了其依赖管理的功能.
}

需要注意的是,在build.gradle文件中,buildscript块和plugin块必须作为前两个块存在,否则会报错的.

然后在configure(allprojects) { project ->...}代码块的apply代码区域新增:

    apply plugin: 'org.springframework.boot'                        //spring boot插件
    apply plugin: 'io.spring.dependency-management'                 //实现maven的依赖统一管理功能

并在顶部添加:

import org.springframework.boot.gradle.plugin.SpringBootPlugin

这样,我们就引入了org.springframework.boot插件,接下来就是使用该插件完成依赖管理的功能.
首先完成基础配置,在包含了apply代码的configure(allprojects){ project -> ...}代码块的底部,加入下面代码,其作用主要是用来配置构建jar包时的一些操作,
bootJar则类似于在maven中springboot插件的repackage功能.

    jar {
           enabled = true
       }
   bootJar {
       launchScript()
       archiveName = "${project.group}_${project.name}_${project.version}.jar"
   }

9.添加使用的jar包的版本.

如果省略掉了步骤5,那么这一步的操作,同样应该放在buildscript代码块中的相应位置.

这一步需要修改 项目根目录/gradle/dependency.gradle文件.

主要是添加 def version=[...]中的数据,修改后,该文件的内容应该如下:

/**
 * ===================================================================================================================
 * -------------------------------------------      统一资源版本控制       ----------------------------------------------
 * ===================================================================================================================
 */

def version = [
        JDK                    : JavaVersion.VERSION_1_8,           //JDK
        JDBC                   : '6.0.6',                           //JDBC
        SPRING_BOOT            : '2.0.1.RELEASE',                   //spring boot 全家桶版本
        SPRING_BOOT_MODELMAPPER: '1.1.0',                           //对象映射工具modelMapper
        SPRING_BOOT_MYBATIS    : '1.3.2',                           //mybatis-spring-boot
        SPRING_BOOT_DRUID      : '1.1.9',                           //druid和spring-boot整合包
        SPRING_CLOUD           : 'Finchley.RELEASE',                //spring cloud全家桶
        ALI_DRUID              : '1.1.9',                           //阿里巴巴druid
        ALI_FASTJSON           : '1.2.47',                          //阿里巴巴fastJson
        PAGEHELPER             : '1.2.3',                           //分页插件
        APACHE_COMMON_LANG3    : '3.4',                             //apache common lang3
        APACHE_COMMON_IO       : '2.6',                             //Apache Commons IO库包含实用程序类,流实现,文件过滤器,文件比较器,endian转换类等等.
]
//统一文件编码控制
def encoding = [
        OPTIONS: 'UTF-8'
]
//暴露参数
ext.custom = [
        version : version,
        encoding: encoding,
]

上面的文件中引入了一些常用的插件,但是本文目前不会涉及到这么多的插件.

10.使用插件进行依赖jar包版本的控制.

在build.gradle文件的底部或者task wrapper(type: Wrapper) {...}的上方输入以下内容:


/**
 * ===================================================================================================================
 * -------------------------------------------      所有子项目的通用配置     ---------------------------------------------
 * ===================================================================================================================
 */
configure(subprojects) {
    project ->
        dependencyManagement {
            overriddenByDependencies = false
            dependencies {
                imports {
                    /**
                     * 通过依赖spring boot dependencies来取代继承spring-boot-starter-parent,
                     * 该配置可以省略.
                     */
                    mavenBom SpringBootPlugin.BOM_COORDINATES

                    /**
                     * 通过依赖spring cloud dependencies 来统一管理spring cloud 的版本
                     */
                    mavenBom "org.springframework.cloud:spring-cloud-dependencies:${custom.version.SPRING_CLOUD}"

                }
                /**
                 * mybatis-spring-boot整合包,该项目必须采用dependency来管理版本,而不能使用mavenBom,
                 * 使用mavenBom可能会导致其依赖的jar包和spring依赖的版本发生冲突.
                 */
                dependency "org.mybatis.spring.boot:mybatis-spring-boot-starter:${custom.version.SPRING_BOOT_MYBATIS}"
                /**
                 * 阿里巴巴druid数据库连接池
                 */
                dependency "com.alibaba:druid:${custom.version.ALI_DRUID}"
                /**
                 * fastJson https://mvnrepository.com/artifact/com.alibaba/fastjson
                 */
                dependency "com.alibaba:fastjson:${custom.version.ALI_FASTJSON}"
                /**
                 * druid数据库连接池和spring-boot整合包
                 */
                dependency "com.alibaba:druid-spring-boot-starter:${custom.version.SPRING_BOOT_DRUID}"
                /**
                 * 分页插件
                 */
                dependency "com.github.pagehelper:pagehelper-spring-boot-starter:${custom.version.PAGEHELPER}"
                /**
                 * 对象实体转换工具包
                 */
                dependency "com.github.jmnarloch:modelmapper-spring-boot-starter:${custom.version.SPRING_BOOT_MODELMAPPER}"
                /**
                 * Apache Commons IO库包含实用程序类,流实现,文件过滤器,文件比较器,endian转换类等等.
                 */
                dependency "commons-io:commons-io:${custom.version.APACHE_COMMON_IO}"

            }
        }
}

这里是使用configure(subprojects) {}还是configure(allprojects) {},取决于父项目是否需要使用这些jar包.
本文中的父项目不需要使用jar包,所以这里采用了subprojects.

这一部分内容,为所有的子模块都添加了依赖版本控制的功能,其功能类似与maven的dependencyManagement.

这里需要注意的是 mavenBom和dependency的用法,如果错误的使用了mavenBom或许将会导致jar包冲突,我之前刚开始使用时错误的将
mybatis-spring-boot使用了mavenBom标签而导致了jar包冲突,这里应该对maven中type为pom类型的文件使用mavenBom.

如果项目报错找不到SpringAppcationBuilder的init方法,八成就是这儿出了问题.

编写到这里,已经完成了对依赖jar包的版本管理,接下来是为项目实际引入jar包.

11.为子项目引入公共jar依赖.

在build.gradle文件的底部或者task wrapper(type: Wrapper) {...}的上方输入以下内容:


configure(subprojects) {
    project ->
        /**
         * -============================================================================================================
         * -=====================================此处存放业务模块的公共依赖==================================================
         * -============================================================================================================
         */
        dependencies {

            /**
             * -=================================================================================-
             * - ********************       [运维]性质相关依赖          *************************** -
             * -=================================================================================-
             */
            //服务监控中心
            compile 'org.springframework.boot:spring-boot-actuator'
            //eureka注册客户端
            compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
            //全局统一配置中心
            compile 'org.springframework.cloud:spring-cloud-starter-config'
            //ribbon负载均衡依赖
            compile 'org.springframework.cloud:spring-cloud-starter-netflix-ribbon'
            //spring cloud openfeign依赖,原feign已经弃用,简化调用方式
            compile 'org.springframework.cloud:spring-cloud-starter-openfeign'
            //spring cloud hystrix 保护模块
            compile 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'

            /**
             * -=================================================================================-
             * - ********************       [工具/功能]性质相关依赖      *************************** -
             * -=================================================================================-
             */
            //Json处理工具
            compile 'com.alibaba:fastjson'
            // Apache Commons IO库包含实用程序类,流实现,文件过滤器,文件比较器,endian转换类等等.
            compile 'commons-io:commons-io'
            //使用lombok来简化掉编码过程中的通用的方法.
            compile 'org.projectlombok:lombok'
            //对象映射工具modelMapper
            compile 'com.github.jmnarloch:modelmapper-spring-boot-starter'
            //spring boot安全依赖
            compile 'org.springframework.boot:spring-boot-starter-security'
            //自定义配置管理
            compile 'org.springframework.boot:spring-boot-configuration-processor'

            /**
             * -=================================================================================-
             * - ********************       [数据库]性质相关依赖        *************************** -
             * -=================================================================================-
             */

            //阿里巴巴druid数据库连接池
            compile 'com.alibaba:druid'

            //jdbc相关配置
            runtime 'mysql:mysql-connector-java'

            // druid数据库连接池和spring-boot整合包
            compile 'com.alibaba:druid-spring-boot-starter'
            //mybatis-spring-boot整合包
            compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter'
            //分页插件
            compile 'com.github.pagehelper:pagehelper-spring-boot-starter'

            //测试依赖
            testCompile 'org.springframework.boot:spring-boot-starter-test'
        }
}

此时,就完成了项目的公共依赖的配置.

12.为子项目引入独有的依赖.

在项目中,除去公共依赖,不同的项目可能会依赖一些特殊的jar包,而这些jar文件又不是共用的,没有必要所有项目都引入,所以就会出现需要单独为每个项目引入jar
包的场景.

针对这种场景,其实有很多种方法来实现,这里我选择的是在子项目的build.gradle文件中配置相关依赖.

进入子项目目录中,并写入依赖配置,此处写入的是eureka的服务端依赖.

cd eureka-demo
echo "dependencies {
    compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
}
">build.gradle

13.屏蔽父项目的构建jar包功能.

因为父项目不提供具体的业务,所以也就不需要打成jar包了,在父项目/build.gradle的底部加入下列代码.

/**
 * 关闭父项目的打包功能
 */
bootJar{
    enabled=false
}
/**
 * 关闭父项目的打包功能
 */
jar{
    enabled=false
}

14.基础构建完成,为子项目实现简单的功能.

在eureka-demo下,新建src/main/java以及src/main/resources目录.

mkdir -p src/main/java
mkdir -p src/main/resources

在src/main/java下构建包结构.

cd src/main/java && mkdir -p cn/jpanda && cd cn/jpanda

创建启动类

touch EurekaStart.java && vim EurekaStart.java

然后输入如下内容:

package cn.jpanda;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class, DataSourceAutoConfiguration.class})
public class EurekaStart {
    public static void main(String[] args) {
        SpringApplication.run(EurekaStart.class, args);
    }
}

之后在当前项目的根目录下执行

sudo gradle build bootJar

该命令将会将eureka项目打包成可执行的jar包.
jar包默认位于:父项目目录/eureka-demo/build/libs/目录下.
进入该目录,可以通过下列命令执行该jar文件.

java -jar <jar包>

截至到这,一个简单的基于gradle搭建的多模块项目的雏形就出来了.

整合docker.(二选一)

在整合docker的过程中遇到了很多哭笑不得的小问题,待会会记录一下.

关于整合docker,在gradle上有很多插件可以实现该功能,这里只针对两个常用的插件进行整合过程的描述.

使用com.palantir.docker插件.

该插件使用简单,但是提供的功能相对较少.

在springboot官网上提供了整合该插件的代码示例,文档地址

其中不仅整合docker插件,也包含了使用gradle构建springboot的示例.

我们就先记录如何使用该插件.

首先修改父项目的build.gradle文件,在其中引入插件com.palantir.docker.

在plugin代码块中添加代码:id "com.palantir.docker" version "0.19.2".

在configure(allprojects) { project ->...}代码块的apply代码区域添加代码apply plugin: 'com.palantir.docker'

之后在文件尾部加入:

configure(subprojects) {
  project ->
    docker {
      dependsOn build
      name "${project.group}/${bootJar.baseName}"
      files bootJar.archivePath
    buildArgs(['JAR_FILE': "${bootJar.archiveName}"])
    }
}

并在eureka-demo目录下新建一个Dockerfile文件,并输入下面内容:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

这样,在eureka-demo下执行命令:

gradle build docker

就会将eureka-demo项目构建成一个镜像.

使用com.bmuschko.docker-java-application和com.bmuschko.docker-remote-api插件

这两个插件是可以单独使用的,其功能非常强大,几乎能够满足所有常用的docker操作.

如果已经使用了com.palantir.docker插件,请先移除相关的操作结果(Dockerfile文件不影响后续操作,可以保留),之后再进行下列操作.

  • step1. 引入com.bmuschko.docker-java-application插件

如果只需要构建镜像文件,可以只引入了com.bmuschko.docker-java-application插件.

  • 在plguins块中插入下列代码.
    id "com.bmuschko.docker-java-application" version "3.3.6"       //通过其远程API管理Docker镜像和容器.
    id "com.bmuschko.docker-remote-api" version "3.3.6"             //Gradle插件,通过其远程API管理Docker镜像和容器.
  • step2.应用该插件

  • 在configure(allprojects) { project ->...}代码块的apply代码区域,应用这两个插件.
   apply plugin: 'com.bmuschko.docker-remote-api'
   apply plugin: 'com.bmuschko.docker-java-application'
  • step3.引入插件依赖的文件,并编写相关的任务.

  • 在文件顶部插入下列代码:
import com.bmuschko.gradle.docker.tasks.image.*
  • 编写相关的任务,将下面的代码放到文件底部.
/**
 * ===================================================================================================================
 * -------------------------------------------      docker相关配置        ---------------------------------------------
 * ===================================================================================================================
 */
configure(subprojects) {
    project ->

        // Dockerfile文件存放地址
        String dockerFileDir = 'build/docker'

        //docker文件
        String dockFilePath = "${dockerFileDir}/Dockerfile"

        docker {
            registryCredentials {
                url = 'tcp://192.168.1.179:2375'
            }
        }

        /**
         * 创建Dockerfile文件.
         */
        task createDockerfile(type: Dockerfile) {
            //指定脚本分组
            group = "docker"
            //脚本依赖 build任务
            dependsOn build
            //指定生成的Dockerfile所处的位置.
            destFile = project.file(dockFilePath)
            //指定依赖的基础镜像
            from 'openjdk:8-jdk-alpine'
            //指定作者信息,但是盖指令在较新的版本中已经被遗弃了,推荐使用label命令.
            maintainer 'Jpanda "jpanda@aliyun.com"'
            //指定挂载目录
            volume "/tmp"
            //扩展标签
            label(['author': 'panda', 'email': 'jpanda@aliyun.com'])
            //添加参数
            arg "JAR_FILE"
            //编译时将jar包保存进去
            copyFile('${JAR_FILE}', "app.jar")
            //指定脚本执行命令
            entryPoint("java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar")
        }
        /**
         * 构建基础镜像
         */
        task image(type: DockerBuildImage) {
            group = 'docker'
            dependsOn createDockerfile
            //指定Dockerfile文件
            inputDir = project.file("build/docker")
            dockerFile = project.file(dockFilePath)
            //标签
            tag = "${project.group}/${project.name}:${project.version}"

            //指定在执行build命令时,使用的构建参数.
            buildArgs = ["JAR_FILE": "${bootJar.archiveName}"]

            /**
             * 在构建容器前,将jar包和Dockerfile放置到同一目录下.
             */
            doFirst {
                copy {
                    from bootJar
                    into "${project.buildDir}/docker"
                }
            }
        }


}

配置中涉及到了一块代码:

docker {
            registryCredentials {
                url = 'tcp://192.168.1.179:2375'
            }
        }

这里的地址可以选择修改为你的docke注册地址.

这里面新增了两个任务,createDockerfile用来生成Dockerfile文件,image用来生成docker镜像.

其中image任务依赖了createDockerfile任务,createDockerfile任务依赖了build任务.

所以我们可以直接在eureka-demo目录下直接输入命令:gradle image来生成镜像文件.

这时候,看最终构建的build.gradle文件内容应该大致如下(内容已经被整理过格式):

import com.bmuschko.gradle.docker.tasks.image.*
import org.springframework.boot.gradle.plugin.SpringBootPlugin

/**
 *
 *   ===================================================================================================================
 *   ===================================================================================================================
 *   ______                         _    _____             __ _                       _   _
 *   |  ____|                       | |  / ____|           / _(_)                     | | (_)
 *   | |__ ___  _ __ _ __ ___   __ _| | | |     ___  _ __ | |_ _  __ _ _   _ _ __ __ _| |_ _  ___  _ __
 *   |  __/ _ \| '__| '_ ` _ \ / _` | | | |    / _ \| '_ \|  _| |/ _` | | | | '__/ _` | __| |/ _ \| '_ \
 *   | | | (_) | |  | | | | | | (_| | | | |___| (_) | | | | | | | (_| | |_| | | | (_| | |_| | (_) | | | |
 *   |_|  \___/|_|  |_| |_| |_|\__,_|_|  \_____\___/|_| |_|_| |_|\__, |\__,_|_|  \__,_|\__|_|\___/|_| |_|
 *   __/ |
 *   |___/
 *   ===================================================================================================================
 *   ===================================================================================================================
 *
 *  step1.项目构建文件,注意,buildscript块和plugins块必须作为build.gradle脚本的前两个块存在,否则会报错.
 *
 */

/**
 * ===================================================================================================================
 * -------------------------------------------       引入项目插件         ----------------------------------------------
 * ===================================================================================================================
 */
plugins {
    id "com.gradle.build-scan" version "1.8"                        //生成构建分析数据.
    id "net.researchgate.release" version "2.7.0"                   //用于向使用Gradle的项目提供类似Maven的发布过程。
    id "com.bmuschko.docker-java-application" version "3.3.6"       //通过其远程API管理Docker镜像和容器.
    id "com.bmuschko.docker-remote-api" version "3.3.6"             //Gradle插件,通过其远程API管理Docker镜像和容器.
    id 'org.springframework.boot' version '2.0.1.RELEASE'           //spring提供的spring boot插件,主要用到了其依赖管理的功能.
}

/**
 * ===================================================================================================================
 * -------------------------------------------      所有项目的通用配置     ----------------------------------------------
 * ===================================================================================================================
 */
configure(allprojects) { project ->
    //项目基础属性
    group 'cn.jpanda'           //项目所属组织
    version '1.0-SNAPSHOT'      //项目版本号

    //引入插件
    apply plugin: 'java'                                            //java插件
    apply plugin: 'maven'                                           //maven插件
    apply plugin: 'idea'                                            //IDEA插件
    apply plugin: 'eclipse'                                         //eclipse插件
    apply plugin: 'org.springframework.boot'                        //spring boot插件
    apply plugin: 'io.spring.dependency-management'                 //实现maven的依赖统一管理功能
    apply plugin: 'com.bmuschko.docker-remote-api'
    apply plugin: 'com.bmuschko.docker-java-application'
    apply from: "${rootProject.rootDir}/gradle/dependency.gradle"   //引入jar包版本配置文件

    //JDK版本声明
    sourceCompatibility = custom.version.JDK
    targetCompatibility = custom.version.JDK

    //配置仓库
    repositories {
        mavenLocal()
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
        maven { url 'https://repo.spring.io/libs-snapshot' }
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
        mavenCentral()
        jcenter()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }

    //指定项目编码
    tasks.withType(JavaCompile) {
        options.encoding = "${custom.encoding.OPTIONS}"
    }

    //在多模块下,授权打包依赖模块
    jar {
        enabled = true
    }

    //重打包基础配置
    bootJar {
//        mainClassName = "jpanda.cloud.EurekaServer"
        launchScript()
        archiveName = "${project.group}_${project.name}_${project.version}.jar"
    }


}
/**
 * ===================================================================================================================
 * -------------------------------------------      所有子项目的通用配置     ---------------------------------------------
 * ===================================================================================================================
 */
configure(subprojects) {
    project ->
        dependencyManagement {
            overriddenByDependencies = false
            dependencies {
                imports {
                    /**
                     * 通过依赖spring boot dependencies来取代继承spring-boot-starter-parent,
                     * 该配置可以省略.
                     */
                    mavenBom SpringBootPlugin.BOM_COORDINATES

                    /**
                     * 通过依赖spring cloud dependencies 来统一管理spring cloud 的版本
                     */
                    mavenBom "org.springframework.cloud:spring-cloud-dependencies:${custom.version.SPRING_CLOUD}"

                }
                /**
                 * mybatis-spring-boot整合包,该项目必须采用dependency来管理版本,而不能使用mavenBom,
                 * 使用mavenBom可能会导致其依赖的jar包和spring依赖的版本发生冲突.
                 */
                dependency "org.mybatis.spring.boot:mybatis-spring-boot-starter:${custom.version.SPRING_BOOT_MYBATIS}"
                /**
                 * 阿里巴巴druid数据库连接池
                 */
                dependency "com.alibaba:druid:${custom.version.ALI_DRUID}"
                /**
                 * fastJson https://mvnrepository.com/artifact/com.alibaba/fastjson
                 */
                dependency "com.alibaba:fastjson:${custom.version.ALI_FASTJSON}"
                /**
                 * druid数据库连接池和spring-boot整合包
                 */
                dependency "com.alibaba:druid-spring-boot-starter:${custom.version.SPRING_BOOT_DRUID}"
                /**
                 * 分页插件
                 */
                dependency "com.github.pagehelper:pagehelper-spring-boot-starter:${custom.version.PAGEHELPER}"
                /**
                 * 对象实体转换工具包
                 */
                dependency "com.github.jmnarloch:modelmapper-spring-boot-starter:${custom.version.SPRING_BOOT_MODELMAPPER}"
                /**
                 * Apache Commons IO库包含实用程序类,流实现,文件过滤器,文件比较器,endian转换类等等.
                 */
                dependency "commons-io:commons-io:${custom.version.APACHE_COMMON_IO}"

            }
        }
}
configure(subprojects) {
    project ->
        /**
         * -============================================================================================================
         * -=====================================此处存放业务模块的公共依赖==================================================
         * -============================================================================================================
         */
        dependencies {

            /**
             * -=================================================================================-
             * - ********************       [运维]性质相关依赖          *************************** -
             * -=================================================================================-
             */
            //服务监控中心
            compile 'org.springframework.boot:spring-boot-actuator'
            //eureka注册客户端
            compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
            //全局统一配置中心
            compile 'org.springframework.cloud:spring-cloud-starter-config'
            //ribbon负载均衡依赖
            compile 'org.springframework.cloud:spring-cloud-starter-netflix-ribbon'
            //spring cloud openfeign依赖,原feign已经弃用,简化调用方式
            compile 'org.springframework.cloud:spring-cloud-starter-openfeign'
            //spring cloud hystrix 保护模块
            compile 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'

            /**
             * -=================================================================================-
             * - ********************       [工具/功能]性质相关依赖      *************************** -
             * -=================================================================================-
             */
            //Json处理工具
            compile 'com.alibaba:fastjson'
            // Apache Commons IO库包含实用程序类,流实现,文件过滤器,文件比较器,endian转换类等等.
            compile 'commons-io:commons-io'
            //使用lombok来简化掉编码过程中的通用的方法.
            compile 'org.projectlombok:lombok'
            //对象映射工具modelMapper
            compile 'com.github.jmnarloch:modelmapper-spring-boot-starter'
            //spring boot安全依赖
            compile 'org.springframework.boot:spring-boot-starter-security'
            //自定义配置管理
            compile 'org.springframework.boot:spring-boot-configuration-processor'

            /**
             * -=================================================================================-
             * - ********************       [数据库]性质相关依赖        *************************** -
             * -=================================================================================-
             */

            //阿里巴巴druid数据库连接池
            compile 'com.alibaba:druid'

            //jdbc相关配置
            runtime 'mysql:mysql-connector-java'

            // druid数据库连接池和spring-boot整合包
            compile 'com.alibaba:druid-spring-boot-starter'
            //mybatis-spring-boot整合包
            compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter'
            //分页插件
            compile 'com.github.pagehelper:pagehelper-spring-boot-starter'

            //测试依赖
            testCompile 'org.springframework.boot:spring-boot-starter-test'
        }
}
/**
 * ===================================================================================================================
 * -------------------------------------------      docker相关配置        ---------------------------------------------
 * ===================================================================================================================
 */
configure(subprojects) {
    project ->

        // Dockerfile文件存放地址
        String dockerFileDir = 'build/docker'

        //docker文件
        String dockFilePath = "${dockerFileDir}/Dockerfile"

        docker {
            registryCredentials {
                url = 'tcp://192.168.1.179:2375'
            }
        }

        /**
         * 创建Dockerfile文件.
         */
        task createDockerfile(type: Dockerfile) {
            //指定脚本分组
            group = "docker"
            //脚本依赖 build任务
            dependsOn build
            //指定生成的Dockerfile所处的位置.
            destFile = project.file(dockFilePath)
            //指定依赖的基础镜像
            from 'openjdk:8-jdk-alpine'
            //指定作者信息,但是盖指令在较新的版本中已经被遗弃了,推荐使用label命令.
            maintainer 'Jpanda "jpanda@aliyun.com"'
            //指定挂载目录
            volume "/tmp"
            //扩展标签
            label(['author': 'panda', 'email': 'jpanda@aliyun.com'])
            //添加参数
            arg "JAR_FILE"
            //编译时将jar包保存进去
            copyFile('${JAR_FILE}', "app.jar")
            //指定脚本执行命令
            entryPoint("java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar")
        }
        /**
         * 构建基础镜像
         */
        task image(type: DockerBuildImage) {
            group = 'docker'
            dependsOn createDockerfile
            //指定Dockerfile文件
            inputDir = project.file("build/docker")
            dockerFile = project.file(dockFilePath)
            //标签
            tag = "${project.group}/${project.name}:${project.version}"

            //指定在执行build命令时,使用的构建参数.
            buildArgs = ["JAR_FILE": "${bootJar.archiveName}"]

            /**
             * 在构建容器前,将jar包和Dockerfile放置到同一目录下.
             */
            doFirst {
                copy {
                    from bootJar
                    into "${project.buildDir}/docker"
                }
            }
        }


}

/**
 * ===================================================================================================================
 * -------------------------------------------          基础配置          ---------------------------------------------
 * ===================================================================================================================
 */

/**
 * 生成gradlew文件,统一gradle版本,避免因为版本不同产生的问题
 */
task wrapper(type: Wrapper) {
    gradleVersion = "4.8"
}
/**
 * 生成构建分析报告.
 */
buildScan {
    licenseAgreementUrl = 'https://gradle.com/terms-of-service'
    //授权
    licenseAgree = 'yes'
}

/**
 * 关闭父项目的打包功能
 */
bootJar{
    enabled=false
}
/**
 * 关闭父项目的打包功能
 */
jar{
    enabled=false
}

其他

  • 项目构建过程中,需要注意执行命令时的用户权限,有些时候可能加上sudo就能解决一些报错.

  • 生成jar包的名称需要注意不要包含特殊符号,包括构建镜像时的jar包.

  • 如果封装了gradle wrapper,不妨使用./gradlew 来代替文中的gradle命令.

  • 脚本对应的项目已经放到了gitee上,点击查看.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容