Java之Gradle【IDEA版】入门到精通(上)(一篇文章精通系列)【安装+基本使用+项目创建+项目部署+文件操作+依赖管理+插件使用】

Gradle文章目录
Java之Gradle【IDEA版】入门到精通(上)(一篇文章精通系列)【安装+基本使用+项目创建+项目部署+文件操作+依赖管理+插件使用】
Java之Gradle【IDEA版】入门到精通(下)(一篇文章精通系列)【创建 Springboot 项目+基于 ssm 多模块项目案例+微服务实战】

Java之Gradle【IDEA版】入门到精通(一篇文章精通系列)

1、Gradle 入门

1.1、Gradle 简介

Gradle 是一款Google 推出的基于 JVM、通用灵活的项目构建工具,支持 Maven,JCenter 多种第三方仓库;支持传递性依赖管理、废弃了繁杂的xml 文件,转而使用简洁的、支持多种语言(例如:java、groovy 等)的 build 脚本文件。
在这里插入图片描述
官网地址: https://gradle.org/
学习Gradle 的原因:

  1. 目前已经有相当一部分公司在逐渐使用Gradle作为项目构建工具了。
  2. 作为Java开发程序员,如果想下载Spring、SpringBoot等Spring家族的源码,基本上基于Gradle构建的。
    总之,虽然目前市面上常见的项目构建工具有Ant、Maven、Gradle,主流还是Maven,但是未来趋势Gradle。

1.2、Gradle 安装

1.2.1 下载解压

Gradle官方下载安装教程页面:https://gradle.org/install/
点击releases page.
在这里插入图片描述
点击:complete (checksums)
在这里插入图片描述
在这里插入图片描述
解压
在这里插入图片描述
在这里插入图片描述

1.2.2 配置环境变量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
GRADLE_HOME

对应刚刚安装的位置路径
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
GRADLE_USER_HOME

对应Maven仓库的位置
在这里插入图片描述

1.2.3 在cmd当中输入命令

gradle -v 或者 gradle --version

通过gradle -v或者 gradle --version检测是否安装成功

Gradle 7.4.2安装成功的提示文本
在这里插入图片描述

1.3、Gradle 项目目录结构

Gradle 项目默认目录结构和Maven 项目的目录结构一致
都是基于约定大于配置【Convention Over Configuration】。其完整项目目录结构如下所示:
在这里插入图片描述
Tips:

  1. 只有war工程才有webapp目录,对于普通的jar工程并没有webapp目录
  2. gradlew与gradlew.bat执行的指定wrapper版本中的gradle指令,不是本地安装的gradle指令哦。

1.4、Gradle 创建第一个项目

1.4.1 通过脚手架创建项目

通过https://start.spring.io/,脚手架创建项目

在这里插入图片描述
在这里插入图片描述

1.4.2 通过Gradle命令创建项目

创建gradle02目录
在这里插入图片描述
进入gradle02目录,在地址栏当中输入cmd
在这里插入图片描述
在这里插入图片描述
输入

gradle init

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
输入no
在这里插入图片描述
在这里插入图片描述
下面直接回车项目名称使用默认文件夹名称
在这里插入图片描述
在这里插入图片描述
创建成功
在这里插入图片描述

1.5 Gradle 中的常用指令

Gradle 常用命令说明:

常用gradle指令作用
gradle clean清空build目录
gradle classes编译业务代码和配置文件
gradle test编译测试代码,生成测试报告
gradle build构建项目
gradle build -x test跳过测试构建

需要注意的是:gradle 的指令要在含有build.gradle 的目录执行。

1.6 修改maven 下载源

Gradle 自带的Maven 源地址是国外的,该Maven 源在国内的访问速度是很慢的,除非使用了特别的手段。

一般情况下,我们建议使用国内的第三方开放的Maven 源或企业内部自建Maven 源。

认识init.d 文件夹

我们可以在gradle 的init.d 目录下创建以.gradle 结尾的文件,.gradle 文件可以实现在build 开始之前执行,所以你可以在这个文件配置一些你想预先加载的操作。

在init.d 文件夹创建init.gradle 文件

在这里插入图片描述

allprojects {
    repositories {
        mavenLocal()
        maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" } 
        maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" } 
        mavenCentral()
    }
    
    buildscript {
        repositories {
            maven { name "Alibaba" ; url 'https://maven.aliyun.com/repository/public' } 
            maven { name "Bstek" ; url 'https://nexus.bsdn.org/content/groups/public/' } 
            maven { name "M2" ; url 'https://plugins.gradle.org/m2/' }
        }
    }
}

在这里插入图片描述

设置M2_HOME的配置
在这里插入图片描述
在这里插入图片描述

拓展说明

拓展 1:启用init.gradle 文件的方法有:

1.在命令行指定文件,例如:gradle --init-script yourdir/init.gradle -q taskName。你可以多次输入此命令来指定多个init文件2.把init.gradle文件放到 USER_HOME/.gradle/ 目录下

  1. 把以.gradle结尾的文件放到 USER_HOME/.gradle/init.d/ 目录下
  2. 把以.gradle结尾的文件放到 GRADLE_HOME/init.d/ 目录下
    如果存在上面的4种方式的2种以上,gradle会按上面的1-4序号依次执行这些文件,如果给定目录下存在多个init脚本,会按拼音a-z顺序执行这些脚本,每个init脚本都存在一个对应的gradle实例,你在这个文件中调用的所有方法和属性,都会委托给这个gradle实例,每个init脚本都实现了Script接口。

拓展 2:仓库地址说明

mavenLocal(): 指定使用maven本地仓库,而本地仓库在配置maven时settings文件指定的仓库位置。
E:/repository,gradle 查找jar包顺序如下:USER_HOME/.m2/settings.xml >> M2_HOME/conf/settings.xml >> USER_HOME/.m2/repository

maven { url 地址},指定maven仓库,一般用私有仓库地址或其它的第三方库【比如阿里镜像仓库地址】。
mavenCentral():这是Maven的中央仓库,无需配置,直接声明就可以使用。
jcenter():JCenter中央仓库,实际也是是用的maven搭建的,但相比Maven仓库更友好,通过CDN分发,并且支持https访问,在新版本中已经废弃了,替换为了mavenCentral()

总之, gradle可以通过指定仓库地址为本地maven仓库地址和远程仓库地址相结合的方式,避免每次都会去远程仓库下载依赖库。

这种方式也有一定的问题,如果本地maven仓库有这个依赖,就会从直接加载本地依赖,如果本地仓库没有该依赖,那么还是会从远程下载。

但是下载的jar不是存储在本地maven仓库中,
而是放在自己的缓存目录中,默认在USER_HOME/.gradle/caches目录,
当然如果我们配置过GRADLE_USER_HOME环境变量,
则会放在GRADLE_USER_HOME/caches目录,那么可不可以将gradle caches指向maven repository

我们说这是不行的,caches下载文件不是按照maven仓库中存放的方式。

拓展 3:阿里云仓库地址请参考:https://developer.aliyun.com/mvn/guide

在这里插入图片描述
在这里插入图片描述

1.7 Wrapper 包装器

Gradle Wrapper 实际上就是对 Gradle 的一层包装,用于解决实际开发中可能会遇到的不同的项目需要不同版本的 Gradle
问题。例如:把自己的代码共享给其他人使用,可能出现如下情况:

  1. 对方电脑没有安装 gradle
  2. 对方电脑安装过 gradle,但是版本太旧了

这时候,我们就可以考虑使用 Gradle Wrapper 了。这也是官方建议使用 Gradle Wrapper 的原因。实际上有了 Gradle Wrapper 之后,我们本地是可以不配置 Gradle 的,下载Gradle 项目后,使用 gradle 项目自带的wrapper 操作也是可以的。
那如何使用Gradle Wrapper 呢?
项目中的gradlew、gradlew.cmd脚本用的就是wrapper中规定的gradle版本。参见源码
而我们上面提到的gradle指令用的是本地gradle,所以gradle指令和gradlew指令所使用的gradle版本有可能是不一样的。
gradlew、gradlew.cmd的使用方式与gradle使用方式完全一致,只不过把gradle指令换成了gradlew指令。
当然,我们也可在终端执行 gradlew 指令时,指定指定一些参数,来控制 Wrapper 的生成,比如依赖的版本等,如下:

参数名说明
–gradle-version用于指定使用的Gradle版本
–gradle-distribution-url用于指定下载Gradle发行版的url地址

在这里插入图片描述
具体操作如下所示 :

gradle wrapper --gradle-version=7.4.2:升级wrapper版本号
只是修改gradle.properties中wrapper版本,

未实际下载

gradle wrapper --gradle-version 7.4.2 --distribution-type all :关联源码用
GradleWrapper 的执行流程:

  1. 当我们第一次执行 ./gradlew build 命令的时候,gradlew 会读取 gradle-wrapper.properties 文件的配置信息
    在这里插入图片描述
  2. 准确的将指定版本的 gradle 下载并解压到指定的位置(GRADLE_USER_HOME目录下的wrapper/dists目录中)
  3. 并构建本地缓存(GRADLE_USER_HOME目录下的caches目录中),下载再使用相同版本的gradle就不用下载了
  4. 之后执行的 ./gradlew 所有命令都是使用指定的 gradle 版本。如下图所示:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

gradle-wrapper.properties 文件解读:

字段名说明
distributionBase下载的Gradle压缩包解压后存储的主目录
distributionPath相对于distributionBase的解压后的Gradle压缩包的路径
zipStoreBase同distributionBase,只不过是存放zip压缩包的
zipStorePath同distributionPath,只不过是存放zip压缩包的
distributionUrlGradle发行版压缩包的下载地址

在这里插入图片描述

注意:前面提到的 GRALE_USER_HOME 环境变量用于这里的Gradle Wrapper 下载的特定版本的gradle 存储目录。
如果我们没有配置过GRALE_USER_HOME 环境变量,默认在当前用户家目录下的.gradle 文件夹中。

那什么时候选择使用 gradle wrapper、什么时候选择使用本地gradle?

下载别人的项目或者使用操作以前自己写的不同版本的gradle项目时:用Gradle wrapper,也即:gradlew

什么时候使用本地gradle?

新建一个项目时: 使用gradle指令即可。

2、Idea当中使用Gradle(普通java 工程)

2.1、在 idea 中创建普通java 工程

具体整合:
第一步:创建由Gradle 管理的项目
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
特别提示 1:使得在Terminal 中执行以gradlew 开头命令和操作图形化的IDEA 使用Gradle 版本不一定是同一个版本哦。
1.Terminal中以gradlew开头指令用的是Wrapper规定的gradle版本,wrapper中规定版本默认和idea插件中规定的版本一致。
2.而图形化的IDEA使用Gradle是本地安装的哦。
特别提示

2:目前只能是在创建项目时重新设置本地gradle,创建新项目需要重新去改。

在这里插入图片描述
在这里插入图片描述
特别提示3:当 我 们 在 gradle.build 文 件 添 加 依 赖 之 后 , 这 些 依 赖 会 在 下 载 到GRADLE_USER_HOME/caches/modules-2/files-2.1 目录下面,所以这里的 GRADLE_USER_HOME 相当于 Gradle 的本地仓库,当然也可以如下方式找到jar 包位置。
在这里插入图片描述

3、在 idea 中创建 web 工程(SSM)

3.1、在idea 创建项目

,无法自己选择创建项目是普通 java 工程还是 web 工程了【IDEA 旧版本是可以的】
,所以我们如果想创建 web 工程,只需要自己在 src/main/目录下添加webapp/WEB-INF/web.xml 及页面即可。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

plugins {
    id 'war'
}

group 'com.itbluebox.gradle'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework:spring-beans:4.1.7.RELEASE'
    implementation 'org.springframework:spring-web:4.1.7.RELEASE'
    implementation 'org.springframework:spring-webmvc:4.1.7.RELEASE'
    implementation 'org.springframework:spring-tx:4.1.7.RELEASE'
    implementation 'org.springframework:spring-test:4.0.5.RELEASE'
    implementation 'org.springframework:spring-jdbc:4.1.7.RELEASE'

    implementation 'org.mybatis:mybatis-spring:1.2.3'
    implementation 'org.mybatis:mybatis:3.3.0'

    implementation 'mysql:mysql-connector-java:8.0.27'
    implementation 'com.alibaba:druid:1.0.15'

    implementation "com.fasterxml.jackson.core:jackson-databind:2.2.3"
    implementation "com.fasterxml.jackson.core:jackson-annotations:2.2.3"
    implementation "com.fasterxml.jackson.core:jackson-core:2.2.3"

    implementation 'org.aspectj:aspectjweaver:1.8.6'
    implementation 'log4j:log4j:1.2.17'
    implementation 'org.slf4j:slf4j-api:1.7.25'
    implementation 'jstl:jstl:1.2'
    compileOnly 'javax.servlet:servlet-api:2.5'

    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

在这里插入图片描述

3.2、创建对应的目录(配置文件)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <context-param>
        <!-- 指定spring 配置文件的路径和名称 -->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <!-- 指定spring的监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 2.配置springmvc的前端控制器 -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 2.处理POST请求乱码的过滤器 -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 3.配置将POST请求转换为PUT或者DELETE请求的过滤器 -->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!-- 0.配置扫描包 -->
    <context:component-scan base-package="com.itbluebox">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>

    <!-- 1.加载properties文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>


    <!-- 2.配置数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.userName}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClassName" value="${jdbc.driverClass}"></property>
    </bean>

    <!-- 4.配置数据源事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>


    <!-- 1.配置spring整合mybatis -->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    </bean>

    <!-- 2.配置扫描mapper接口的bean对象 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itbluebox.dao"/>
    </bean>

</beans>

在这里插入图片描述

jdbc.jdbcUrl=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.userName=root
jdbc.password=root

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>



</configuration>

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
      <!-- 1.配置扫描包 -->
    <context:component-scan base-package="com.itbluebox" use-default-filters="false">
         <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
         <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>
     <!-- 2.配置内部资源视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--3.处理静态资源文件 -->
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>
</beans>

在这里插入图片描述
在这里插入图片描述

3.3、创建响应的数据库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
添加一些数据
在这里插入图片描述

3.4、创建实体类和相关的service和controller

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


public class Admin {
    private Integer id;
    private String username;
    private String email;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Admin{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

public interface AdminMapper {
    List<Admin> getAdminList();
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@Service
public class AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Transactional
    public List<Admin> getAdminList(){
        return adminMapper.getAdminList();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@Controller
@RequestMapping("/admin")
public class AdminController {

    @Autowired
    private AdminService adminService;


    @RequestMapping("/list")
    @ResponseBody
    public List<Admin> getAdminList() {
        System.out.println("dada");
        return adminService.getAdminList();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itbluebox.dao.AdminMapper">

    <select id="getAdminList" resultType="com.itbluebox.bean.Admin">
        select id,username,email from admin
    </select>

</mapper>

4、项目部署(Tomcat)

4.1、配置Tomcat

当我们将一个 java 项目打成war 包之后,就需要部署到服务器运行,这里有两种方式:
● 我们将项目打成 war 包,部署到本地tomcat 运行:演示
在这里插入图片描述
选择安装好的Tomcat
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.2、启动测试运行

在这里插入图片描述
http://localhost:8080/ssm/admin/list
在这里插入图片描述

5、Gretty 部署项目

Gretty 是一个功能丰富的 gradle 插件,用于在嵌入的 servlet 容器上运行 web 应用程序,让项目开发和部署更加简单。目前Gretty 插件已经作为 gradle 的核心库使用了,Gretty 其核心功能为:

  1. 底层支持 jetty,tomcat 等Servlet 容器
  2. 支持项目热部署、HTTPS、调试
    Gretty 官网地址:http://akhikhl.github.io/gretty-doc/index.html

5.1、具体使用

第一步:引入 Gretty 插件

plugins {
    id 'war'
	    id 'org.gretty' version '2.2.0'
}

第二步:指定maven 仓库

repositories {
    //指定jcenter仓库,一定要放在前面
    jcenter() 
    mavenCentral()
}

第三步:针对Gretty 插件的设置

gretty {
    httpPort = 8888
    contextPath = "/web"
    debugPort = 5005	// default 
    debugSuspend = true // default 
    httpsEnabled = true
    managedClassReload=true // 修改了类之后重新加载
    //servletContainer = 'tomcat8' //如果不指定默认的servlet容器,支持tomcat7/8,默认是使用的是Jetty服务器
    httpsPort = 4431
}

在这里插入图片描述

第四步:执行Gretty 插件
在这里插入图片描述

gradle appRun

如 果 大 家 想 进 一 步 了 解 的 属 性 配 置 , 比 如 Gretty 热 部 署 等 设 置 , 欢 迎 参 考 其 官 方 文 档
http://akhikhl.github.io/gretty-doc/Gretty-configuration.html

6、Gretty 对测试的支持

测试任务自动检测并执行测试源集中的所有单元测试。测试执行完成后会生成一个报告。支持JUnit 和 TestNG 测试。

6.1、默认测试目录及标准输出

在这里插入图片描述

6.2、Junit 使用

6.2.1、引入依赖

Gradle 对于Junit4.x 支持

dependencies {
    testImplementation group: 'junit' ,name: 'junit', version: '4.12'
}
test {
    useJUnit()
}

Gradle 对于Junit5.x 版本支持
在这里插入图片描述

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' 
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
test {
    useJUnitPlatform()
}

注意:无论是 Junt4.x 版本还是Junit5.x 版本,我们只需在 build.gradle 目录下执行gradle test 指令,gradle 就会帮我们执行所有的加了@Test 注解的测试,并生成测试报告。

6.2.2、编写测试类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


public class AppTest {

    @Test
    public void testMethod1(){
        System.out.println("test itbluebox method1");
    }

}

6.2.3、运行测试

在这里插入图片描述

生成测试包
在这里插入图片描述
在这里插入图片描述

6.2.4、跳过测试类

在这里插入图片描述
enabled值为FALSE的时候跳过测试类,为true的时候不跳过测试类

enabled(false) //跳过测试类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.2.5、指定执行某个包下的测试类

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

public class AppTest {
    @Test
    public void testMethod2(){ 
        System.out.println("test itbluebox method2");
    }
}

在这里插入图片描述

  include('com/itbluebox/bj/')

或者

  include('com/itbluebox/bj/**')

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.2.6、排除某个包下的测试类

在这里插入图片描述

    //include('com/itbluebox/bj/')
    exclude("com/itbluebox/bj/**") //设置排除某个包下的测试类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7、Gradle 进阶说明

为了让大家快速的入门gradle,本章将从整体构建脚本的角度介绍:
● 什么是 setting 文件,它有什么作用;
● 说明什么是build 文件,它又有什么作用
● 我们可以创建多少个 build
● project 和task,他们有什么作用;又是什么关系,如何配置
● 项目的生命周期
● 项目发布
● 使用Gradle 创建SpringBoot 项目等

7.1、项目的生命周期

Gradle 项目的生命周期分为三大阶段: Initialization -> Configuration -> Execution.
每个阶段都有自己的职责,具体如下图所示:
在这里插入图片描述
Initialization 阶段主要目的是初始化构建, 它又分为两个子过程,一个是执行 Init Script,另一个是执行 Setting Script。
init.gradle 文件会在每个项目 build 之前被调用,用于做一些初始化的操作,它主要有如下作用:
○ 配置内部的仓库信息(如公司的 maven 仓库信息);
○ 配置一些全局属性;
○ 配置用户名及密码信息(如公司仓库的用户名和密码信息)。
Setting Script 则更重要, 它初始化了一次构建所参与的所有模块。
Configuration 阶段:这个阶段开始加载项目中所有模块的 Build Script。所谓 “加载” 就是执行 build.gradle 中的语句, 根据脚本代码创建对应的 task, 最终根据所有 task 生成由 Task 组成的有向无环图(Directed Acyclic Graphs),如下:
在这里插入图片描述
从而构成如下有向无环树:
在这里插入图片描述
Execution 阶段:这个阶段会根据上个阶段构建好的有向无环图,按着顺序执行 Task【Action 动作】。

7.2、settings 文件

首先对 settings 文件的几点说明:
1、作用:主要是在项目初始化阶段确定一下引入哪些工程需要加入到项目构建中,为构建项目工程树做准备。
2、工程树:gradle 中有工程树的概念,类似于 maven 中的project 与module。
在这里插入图片描述

3、内容:里面主要定义了当前 gradle 项目及子 project 的项目名称
4、位置:必须放在根工程目录下。
5、名字:为settings.gradle 文件,不能发生变化
6、对应实例:与 org.gradle.api.initialization.Settings 实例是一一对应的关系。每个项目只有一个settings 文件。
7、关注:作为开发者我们只需要关注该文件中的include 方法即可。使用相对路径【 : 】引入子工程。
8.一个子工程只有在setting 文件中配置了才会被 gradle 识别,这样在构建的时候才会被包含进去。案例如下所示:

//根工程项目名
rootProject.name = 'root'
//包含的子工程名称
include 'subject01' 
include 'subject02' 
include 'subject03'
//包含的子工程下的子工程名称
include 'subject01:subproject011' 
include 'subject01:subproject012'

项目名称中 “:” 代表项目的分隔符, 类似路径中的 “/”. 如果以 “:” 开头则表示相对于 root project 。然后 Gradle 会为每个带有 build.gradle 脚本文件的工程构建一个与之对应的 Project 对象。

7.3、Task

项目实质上是 Task 对象的集合。一个 Task 表示一个逻辑上较为独立的执行过程,比如编译Java 源代码,拷贝文件, 打包Jar 文件,甚至可以是执行一个系统命令。另外,一个 Task 可以读取和设置Project 的Property 以完成特定的操作。

7.3.1、任务入门

可参考官方文档:https://docs.gradle.org/current/userguide/tutorial_using_tasks.html
让我们来先看一个例子:
在这里插入图片描述

task task1{
    //定义任务的配置段:在项目的生命周期的配置阶段
    println "最简单的任务"
    //配置任务的行为:在执行阶段执行,doFirst会在doLast执行之前执行
    doFirst(){
        println "task1 doFirst"
    }
    doLast(){
        println "task1 doLast"
    }
}

在文件所在的目录执行命令: gradle -i task1

#日志选项 看详细信息
gradle -i

提示 1 :task 的配置段是在配置阶段完成

提示 2 :task 的doFirst、doLast 方法是执行阶段完成,并且doFirst 在doLast 执行之前执行。

提示 3:区分任务的配置段和任务的行为,任务的配置段在配置阶段执行,任务的行为在执行阶段执行

在这里插入图片描述
在这里插入图片描述

7.3.2、任务的行为

案例如下:doFirst、doLast 两个方法可以在任务内部定义,也可以在任务外部定义
在这里插入图片描述

def map=new HashMap<String,Object>();
//action属性可以设置为闭包,设置task自身的行为
map.put("action",{println "taskD.."})
task(map,"a"){
    description   'taskA description	'
    group "atguigu"
    //在task内部定义doFirst、doLast行为
    doFirst {
        def name = 'doFirst..' 
        println name
    }
    doLast {
        def name = 'doLast..' 
        println name
    }
}
//在task外部定义doFirst、doLast行为
a.doFirst {
    println it.description
}
a.doLast {
    println it.group
}

执行gradle clean

在这里插入图片描述
输入:gradle a
在这里插入图片描述
底层原理分析:
在这里插入图片描述

无论是定义任务自身的 action,还是添加的doLast、doFirst 方法,其实底层都被放入到一个Action 的List 中了,最初这个 action List 是空的,当我们设置了 action【任务自身的行为】,它先将action 添加到列表中,此时列表中只有一个action,后续执行doFirst 的时候doFirst 在action 前面添加,执行 doLast 的时候doLast 在action 后面添加。doFirst 永远添加在actions List 的第一位,保证添加的Action 在现有的 action List 元素的最前面;

doLast 永远都是在action List 末尾添加,保证其添加的Action 在现有的action List 元素的最后面。

一个往前面添加,一个往后面添加,最后这个action List 就按顺序形成了doFirst、doSelf、doLast 三部分的 Actions,就达到 doFirst、doSelf、doLast 三部分的 Actions 顺序执行的目的。

提示 1:其中<<代表doLast,在gradle5.x 版本之后就废弃,不能使用了,如下所示:

task hello << {
    println 'Hello world!'
}
7.3.3、任务的依赖方式

Task 之间的依赖关系可以在以下几部分设置:

  1. 参数依赖
  2. 内部依赖
  3. 外部依赖

方式一:参数方式依赖
在这里插入图片描述

task A {
    doLast {
        println "TaskA.."
    }
}
task 'B' {
    doLast {
        println "TaskB.."
    }
}
//参数方式依赖: dependsOn后面用冒号
task 'C'(dependsOn: ['A', 'B']) {
    doLast {
        println "TaskC.."
    }
}

运行测试

gradle C

在这里插入图片描述

方式二:内部依赖
在这里插入图片描述

//参数方式依赖
task 'C' {
    //内部依赖:dependsOn后面用 = 号
    dependsOn= [A,B] 
    doLast {
        println "TaskC.."
    }
}
gradle clean

在这里插入图片描述

gradle C

在这里插入图片描述
方式三:外部依赖

  • 外部依赖:可变参数,引号可加可不加

在这里插入图片描述

task A {
    doLast {
        println "TaskA.."
    }
}
task 'B' {
    doLast {
        println "TaskB.."
    }
}
//参数方式依赖: dependsOn后面用冒号
task 'C'() {

    doLast {
        println "TaskC.."
    }
}
C.dependsOn = ['A', 'B']
gradle clean

在这里插入图片描述

 gradle C

在这里插入图片描述

C.dependsOn(B,'A')

当然:task 也支持跨项目依赖
subproject01 工程的 build.gradle 文件中定义:

task A {
    doLast {
        println "TaskA.."
    }
}

subproject02 工程的 build.gradle 文件中定义:

task B{
    dependsOn(":subproject01:A") //依赖根工程下的subject01中的任务A :跨项目依赖。
    doLast {
        println "TaskB.."
    }
}

测试:gradle B ,控制台显示如下
在这里插入图片描述
拓展 1:当一个 Task 依赖多个Task 的时候,被依赖的Task 之间如果没有依赖关系,那么它们的执行顺序是随机的,并无影响。

拓展 2:重复依赖的任务只会执行一次,比如:

A->BC 
B->C

任务A 依赖任务 B 和任务 C、任务 B 依赖C 任务。执行任务A 的时候,显然任务C 被重复依赖了,C 只会执行一次。

7.3.4、任务执行(常用命令)

任务执行语法:gradle [taskName...] [--option-name...]

分类解释
常见的任务(*)在这里插入图片描述
项目报告相关任务在这里插入图片描述
调试相关选项在这里插入图片描述
性能选项:【备注: 在gradle.properties 中指定这些选项中的许多选项,因此不需要命令行标志】在这里插入图片描述
守护进程选项在这里插入图片描述
日志选项在这里插入图片描述
其它(*)在这里插入图片描述
(1)gradle run :运行一个服务,需要application 插件支持,并且指定了主启动类才能运行

切换回项目2
在这里插入图片描述

定义main方法

在这里插入图片描述
指定main方法所在类的路径
在这里插入图片描述
运行
在这里插入图片描述
在这里插入图片描述
或者

gradle -w run

在这里插入图片描述

gradle run

在这里插入图片描述
显示项目目录结构

gradle projects

在这里插入图片描述
切换回web项目
在这里插入图片描述

(2)gradle task 列出所选项目【当前 project,不包含父、子】的已分配给任务组的那些任务。
gradle task

在这里插入图片描述
在这里插入图片描述
指定对应的任务分组
在这里插入图片描述

group "abc"

可以看到对应的分组信息
在这里插入图片描述

在这里插入图片描述

(3)gradle tasks --all :列出所选项目的所有任务。

在这里插入图片描述

(4)gradle tasks --group="build setup":列出所选项目中指定分组中的任务。
 gradle tasks --group="abc"  

在这里插入图片描述

(5)gradle help --task someTask :显示某个任务的详细信息
gradle help --task B 

在这里插入图片描述

(6)gradle dependencies :查看整个项目的依赖信息,以依赖树的方式显示

在这里插入图片描述
在这里插入图片描述

(7)gradle properties 列出所选项目的属性列表

在这里插入图片描述

(8)gradle --help 列出所有命令

在这里插入图片描述

(9)gradle init --type pom :将maven 项目转换为gradle 项目(根目录执行)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

gradle init --type pom

在这里插入图片描述
在这里插入图片描述

修改成功
在这里插入图片描述
在这里插入图片描述

(10)gradle [taskName] :执行自定义任务

gradle-web项目当中

在这里插入图片描述

task connectionTask {
    doLast {
        println "TaskA.."
    }
}
gradle cT

在这里插入图片描述
更 详 细 请 参 考 官 方 文 档 : https://docs.gradle.org/current/userguide/command_line_interface.html#sec:command_line_executing_tasks
拓展:gradle 任务名是缩写: 任务名支持驼峰式命名风格的任务名缩写,如:connectTask 简写为:cT,执行任务 gradle cT。
拓展 1:前面提到的Gradle 指令本质:一个个的task[任务], Gradle 中所有操作都是基于任务完成的。
在这里插入图片描述
拓展 2:gradle 默认各指令之间相互的依赖关系:
在这里插入图片描述

7.3.5、任务定义方式

任务定义方式,总体分为两大类:一种是通过 Project 中的task()方法,另一种是通过tasks 对象的 create 或者register 方法。
在这里插入图片描述


task('A',{//任务名称,闭包都作为参数println "taskA..."
    println "taskA..."
})
task('B'){//闭包作为最后一个参数可以直接从括号中拿出来println "taskB..."
    println "taskB..."
}
task C{//groovy语法支持省略方法括号:上面三种本质是一种println "taskC..."
    println "taskC..."
}

def map=new HashMap<String,Object>();

map.put("action",{
    println "taskD.."
}) //action属性可以设置为闭包

task(map,"D");

tasks.create('E'){//使用tasks的create方法
    println "taskE.."
}
tasks.register('f'){ //注:register执行的是延迟创建。也即只有当task被需要使用的时候才会被创建。
    println "taskF	"
}
gradle build

在这里插入图片描述

gradle f

在这里插入图片描述

当然:我们也可以在定义任务的同时指定任务的属性,具体属性有:
在这里插入图片描述
在定义任务时也可以给任务分配属性:
定义任务的时候可以直接指定任务属性,也可以给已有的任务动态分配属性:
在这里插入图片描述

//①.F是任务名,前面通过具名参数给map的属性赋值,以参数方式指定任务的属性信息
task(group: "itbluebox",description: "this is task B","F")
//②.H是任务名,定义任务的同时,在内部直接指定属性信息
task("H") {
    group("itbluebox")
    description("this is the task H")
}
//③.Y是任务名,给已有的任务 在外部直接指定属性信息
task "y"{}
y.group="itbluebox"
clean.group("itbluebox") //案例:给已有的clean任务重新指定组信息

可以在 idea 中看到:
上面自定义的那几个任务和 gradle 自带的 clean 任务已经跑到:itbluebox组了。
在这里插入图片描述
在这里插入图片描述

7.3.6、任务类型

前面我们定义的task 都是DefaultTask 类型的,如果要完成某些具体的操作完全需要我们自己去编写gradle 脚本,
势必有些麻烦,
那有没有一些现成的任务类型可以使用呢?

有的,Gradle 官网给出了一些现成的任务类型帮助我们快速完成想要的任务,
我们只需要在创建任务的时候,指定当前任务的类型即可,
然后即可使用这种类型中的属性和API 方法了。

常见任务类型该类型任务的作用
Delete删除文件或目录
Copy将文件复制到目标目录中。此任务还可以在复制时重命名和筛选文件。
CreateStartScripts创建启动脚本
Exec执行命令行进程
GenerateMavenPom生成 Maven 模块描述符(POM)文件。
GradleBuild执行 Gradle 构建
Jar组装 JAR 归档文件
JavaCompile编译 Java 源文件
Javadoc为 Java 类 生 成 HTML API 文 档
PublishToMavenRepository将 MavenPublication 发布到 mavenartifactrepostal。
Tar组装 TAR 存档文件
Test执行 JUnit (3.8.x、4.x 或 5.x)或 TestNG 测试。
Upload将 Configuration 的构件上传到一组存储库。
War组装 WAR 档案。
Zip组装 ZIP 归档文件。默认是压缩 ZIP 的内容。

在这里插入图片描述

tasks.register('myClean',Delete){
    delete buildDir
}

执行下面命令删除build目录

gradle myClean

在这里插入图片描述
自定义 Task 类型
在这里插入图片描述

def myTask=task MyDefinitionTask (type: CustomTask)

myTask.doFirst(){
    println "task 执行之前 执行的 doFirst方法"
}

myTask.doLast(){
    println "task 执行之后 执行的 doLast方法"
}

class CustomTask extends DefaultTask {
    //@TaskAction表示Task本身要执行的方法@TaskAction
    def doSelf(){
        println "Task 自身 在执行的in doSelf"
    }
}

测试:gradle MyDefinitionTask
在这里插入图片描述
放开注释内容

在这里插入图片描述
测试:gradle MyDefinitionTask
在这里插入图片描述

7.3.7、任务的执行顺序

在 Gradle 中,有三种方式可以指定 Task 执行顺序:
1、dependsOn 强依赖方式
2、通过 Task 输入输出
3、通过 API 指定执行顺序
详细请参考官网:https://docs.gradle.org/current/dsl/org.gradle.api.Task.html

7.3.8、动态分配任务

gradle 的强大功能不仅仅用于定义任务的功能。例如,可以使用它在循环中注册同一类型的多个任务

4.times { counter ->
    tasks.register("task$counter") {
        doLast {
            println "I'm task number $counter"
        }
    }
}

一旦注册了任务,就可以通过 API 访问它们。例如,您可以使用它在运行时动态地向任务添加依赖项。Ant 不允许这样的事情发生。

构建 4 个任务,但是任务 0 必须依赖于任务 2 和 3,那么代表任务 2 和 3 需要在任务 0 之前优先加载。具体测试如下:

4.times { counter -> 
    tasks.register("task$counter") {
        doLast {
            println "I'm task number $counter"
        }
    }
}
tasks.named('task0') {
    dependsOn('task2', 'task3')
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.3.9、任务的关闭与开启

每个任务都有一个 enabled 默认为的标志 true。将其设置为 false 阻止执行任何任务动作。禁用的任务将标记为“跳过”。

在这里插入图片描述

task2.enabled = false

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

7.3.10、任务的超时

每个任务都有一个 timeout 可用于限制其执行时间的属性。
当任务达到超时时,其任务执行线程将被中断。该任务将被标记为失败。终结器任务仍将运行。
如果 --continue 使用,其他任务可以在此之后继续运行。
不响应中断的任务无法超时。
Gradle 的所有内置任务均会及时响应超时

删除之前的内容,添加如下内容
在这里插入图片描述

task a() {
	doLast {
		Thread.sleep(1000)
		println "当前任务a执行了"
	}
	timeout = Duration.ofMillis(500)
}
task b() {
	doLast {
		println "当前任务b执行了"
	}
}

在控制台使用:
gradle a b 测试会发现执行a 的时候,由于a 执行超时,抛出异常,所以没有继续往下执行【b 也没执行】
在这里插入图片描述

然后在控制台使用: gradle a b -continue,测试会发现a 虽然执行失败,但是 b 还是执行了。
在这里插入图片描述

7.3.11、任务的查找

在这里插入图片描述

task itbluebox {
	doLast {
		println "itbluebox dolast"
	}
}
//根据任务名查找
tasks.findByName("itbluebox").doFirst({println "itbluebox1:北京	"})
tasks.getByName("itbluebox").doFirst({println "itbluebox2:深圳	"})
//根据任务路径查找【相对路径】
tasks.findByPath(":itbluebox").doFirst({println "itbluebox3:上海"}) tasks.getByPath(":itbluebox").doFirst({println "itbluebox4:武汉	"})
gradle itbluebox

在这里插入图片描述

7.3.12、任务的规则

当我们执行、依赖一个不存在的任务时,
Gradle 会执行失败,报错误信息。
那我们能否对其进行改进,当执行一个不存在的任务时,
不是报错而是打印提示信息呢?
在这里插入图片描述

task hello {
	doLast {
		println 'hello itbluebox 的粉丝们'
	}
}

tasks.addRule("对该规则的一个描述,便于调试、查看等"){ 
	String taskName -> task(taskName) {
		doLast {
			println "该${taskName}任务不存在,请查证后再执行"
		}
	}
}

测试: 使用

gradle abc hello

进行测试,此时当 abc 任务不存在时,
也不会报异常【不中断执行】
而是提示自定义的规则信息,
继续执行 hello 任务。
在这里插入图片描述

此外,它还可以根据不同的规则动态创建需要的任务等情况。

7.3.13、任务的 onlyIf 断言

断言就是一个条件表达式。Task 有一个 onlyIf 方法。

它接受一个闭包作为参数,如果该闭包返回 true 则该任务执行, 否则跳过。

这有很多用途,比如控制程序哪些情况下打什么包,什么时候执行单元测试,
什么情况下执行单元测试的时候不执行网络测试等。具体案例如下所示:

task hello {
	doLast {
	println 'hello itbluebox的粉丝们'
	}
}

hello.onlyIf { !project.hasProperty('fensi') }

在这里插入图片描述

测试

gradle hello

在这里插入图片描述
通过-P 为Project 添加fensi 属性

gradle hello -Pfensi

在这里插入图片描述

7.3.14、默认任务

Gradle 允许您定义一个或多个在没有指定其他任务时执行的默认任务。代码如下所示:

defaultTasks 声明默认任务

defaultTasks 'myClean', 'myRun'

tasks.register('myClean'){
	doLast {
		println 'Default Cleaning!'
	}
}

tasks.register('myRun') { 
	doLast {
		println 'Default Running!'
	}
}

tasks.register('other') { 
	doLast {
		println "I'm not a default task!"
	}
}

在这里插入图片描述

gradle -q 

在这里插入图片描述

8、Gradle 中的文件操作

几种常见的文件操作方式:
● 本地文件
● 文件集合
● 文件树
● 文件拷贝
● 归档文件
各种文件操作类型的详细介绍如下所示:

8.1、本地文件

使用 Project.file(java.lang.Object)方法,
通过指定文件的相对路径或绝对路径来对文件的操作,
其中相对路径为相对当前project[根project 或者子project]的目录。

其实使用 Project.file(java.lang.Object)方法创建的 File 对象就是 Java 中的 File 对象,
我们可以使用它就像在 Java 中使用一样。

示例代码如下:

  • (1)使用本地文件的方式,使用的是相对路径
//使用相对路径
File configFile = file('src/conf.xml')
configFile.createNewFile();

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建成功
在这里插入图片描述

  • (2)使用本地文件的方式,使用绝对路径
// 使用绝对路径
File configFile = file('D:\\conf.xml');
configFile.createNewFile();

在这里插入图片描述
运行成功
在这里插入图片描述
创建成功
在这里插入图片描述

  • (3)使用本地文件的方式,new File
// new File
File configFile = new File("itbluebox.xml")
configFile.createNewFile();

在这里插入图片描述
在这里插入图片描述
运行成功并创建成功
在这里插入图片描述

// 使用一个文件对象
configFile = new File('src/config.xml')
println(configFile.exists())

8.2、文件集合

文 件 集 合 就 是 一 组 文 件 的 列 表 , 在 Gradle 中 , 文 件 集 合 用 FileCollection 接 口 表 示 。 我 们 可 以 使 用。
在这里插入图片描述

//方式2.通过文件集合的方式
FileCollection fileCollection = files('src/text1.xml',['src/text2.xml','src/text3.xml'])
fileCollection.forEach(item->{
    println item.name
})

在这里插入图片描述

在这里插入图片描述
创建文件
在这里插入图片描述

//方式2.通过文件集合的方式
FileCollection fileCollection = files('src/text1.xml',['src/text2.xml','src/text3.xml'])
fileCollection.forEach(item->{
    item.createNewFile()
})

在这里插入图片描述
创建成功
在这里插入图片描述
在这里插入图片描述

Set set = fileCollection.files // 把文件集合转换为java中的Set类型

for (final def i in set){
    println i.exists()
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Set set2 = fileCollection as Set

for (final def i in set2){
    println i.exists()
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

List list = fileCollection as List

for (final def i in list){
    println i.exists()
}

在这里插入图片描述
在这里插入图片描述

println "\nAdd file set\n"
def union = fileCollection + files('src/text4.xml') // 添加或者删除一个集合
union.forEach(){File it ->
    println it.name
}

println "\nMinus file set\n"
def minus = fileCollection - files('src/text1.xml')
minus.forEach(){File it ->
    println it.name
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对于文件集合我们可以遍历它;

也可以把它转换成java 类型;

同时还能使用+来添加一个集合,或使用-来删除集合。

8.3、文件树

文件树是有层级结构的文件集合,
一个文件树它可以代表一个目录结构或一 ZIP 压缩包中的内容结构。

文件树是从文件集合继承过来的,所以文件树具有文件集合所有的功能。

我们可以使用 Project.fileTree(java.util.Map)方法来创建文件树对象,

还可以使用过虑条件来包含或排除相关文件。

示例代码如下:
在这里插入图片描述

ConfigurableFileTree configurableFileTree = fileTree('src/main')
configurableFileTree.forEach(item-> {
    println item.name
})

在这里插入图片描述

在这里插入图片描述

include 指定对应筛选文件("**/*.java"筛选以.java后缀的文件)
在这里插入图片描述


ConfigurableFileTree configurableFileTree = fileTree('src/main')
configurableFileTree.include("**/*.java").forEach(item-> {
    println item.name
})

在这里插入图片描述

在这里插入图片描述
exclude排除不符合条件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

tree = fileTree('src/main').include('**/*.java')// 第一种方式:使用路径创建文件树对象,同时指定包含的文件

//第二种方式:通过闭包创建文件树:

tree = fileTree('src/main') {
	include '**/*.java'
}

tree = fileTree(dir: 'src/main', include: '**/*.java') 
//第三种方式:通过路径和闭包创建文件树:具名参数给map传值

tree = fileTree(dir: 'src/main', includes: ['**/*.java', '**/*.xml', '**/*.txt'], exclude: '**/*test*/**')
	tree.each {File file -> // 遍历文件树的所有文件
	println file println file.name
}

8.4、文件拷贝

我们可以使用 Copy 任务来拷贝文件,通过它可以过虑指定拷贝内容,
还能对文件进行重命名操作等。
Copy 任务必须指定一组需要拷贝的文件和拷贝到的目录,
这里使用CopySpec.from(java.lang.Object[])方法指定原文件;
使用CopySpec.into(java.lang.Object)方法指定目标目录。
示例代码如下

task copyTask(type: Copy) { 
	from 'src/main/resources' into 'build/config'
}

from()方法接受的参数和文件集合时files()一样。
当参数为一个目录时,该目录下所有的文件都会被拷贝到指定目录下(目录自身不会被拷贝);
当参数为一个文件时,该文件会被拷贝到指定目录;
如果参数指定的文件不存在,就会被忽略;
当参数为一个 Zip 压缩文件,该压缩文件的内容会被拷贝到指定目录。
into()方法接受的参数与本地文件时 file()一样。 示例代码如下
在这里插入图片描述

task copyTask(type: Copy) {
	// 拷贝src/main/webapp目录下所有的文件
	from 'src/main/webapp'
	// 拷贝单独的一个文件
	from 'src/staging/index.html'
	// 从Zip压缩文件中拷贝内容
	from zipTree('src/main/assets.zip')
	// 拷贝到的目标目录
	into 'build/explodedWar'
}

在这里插入图片描述
在这里插入图片描述

在拷贝文件的时候还可以添加过虑条件来指定包含或排除的文件,示例如下:
在这里插入图片描述

task copyTask(type: Copy) {
    // 拷贝src/main/目录下所有的文件
    from 'src/main/'
    include("**/*.java","**/*.jsp","**/*.xml")
    exclude("**/*.jsp")

    // 拷贝到的目标目录
    into 'build/explodedWar'
}

在这里插入图片描述

在这里插入图片描述
运行成功
在这里插入图片描述

在拷贝文件的时候还可以对文件进行重命名操作,示例如下:
在这里插入图片描述

task copyTask(type: Copy) {
    // 拷贝src/main/目录下所有的文件
    from 'src/main/java/com/itbluebox/bean/Admin.java'
    // 使用一个闭包方式重命名文件
    rename {
        String fileName -> fileName.replace('Admin', 'AdminTest')
    }
    // 拷贝到的目标目录
    into 'build/explodedWar'
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在上面的例子中我们都是使用Copy 任务来完成拷贝功能的,那么有没有另外一种方式呢?答案是肯定的,那就是
Project.copy(org.gradle.api.Action)方法。下面示例展示了 copy()方法的使用方式:

task copyMethod { 
	doLast {
		copy {
			from 'src/main/webapp' 
			into 'build/explodedWar' 
			include '**/*.html' include '**/*.jsp'
		}
	}
}

或者使用project 对象的copy 方法:
在这里插入图片描述


copy {
    //相对路径或者绝对路径
    from file('src/main/resources/jdbc.properties') //file也可以换成new File()
    into this.buildDir.absolutePath
}

在这里插入图片描述
执行gradle build 指令即可。去 build 目录的本地磁盘查看,就能看到。
在这里插入图片描述
在这里插入图片描述

8.5、文件归档

通常一个项目会有很多的 Jar 包,我们希望把项目打包成一个 WAR,ZIP 或 TAR 包进行发布,这时我们就可以使用Zip,Tar,Jar,War 和Ear 任务来实现,不过它们的用法都一样,所以在这里我只介绍Zip 任务的示例。首先,创建一个 Zip 压缩文件,并指定压缩文件名称,如下代码所示:
在这里插入图片描述

apply plugin: 'java' version=1.0
task myZip(type: Zip) { 
	from 'src/main‘
	into ‘build’ //保存到build目录中
	baseName = 'myGame'
}
println myZip.archiveName

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

执行命令gradle -q myZip,输出结果为:
在这里插入图片描述
压缩为tar

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后,我们可以使用 Project.zipTree(java.lang.Object)Project.tarTree(java.lang.Object)方法来创建访问 Zip 压缩包的文件树对象,示例代码如下:

// 使用zipTree
FileTree zip = zipTree('someFile.zip')
// 使用tarTree
FileTree tar = tarTree('someFile.tar')

在这里,我们介绍了 Gradle 对本地文件、文件集合、文件树、文件拷贝和归档文件的操作方式。更详细的请参考官方文档:https://docs.gradle.org/current/userguide/working_with_files.html

9、Dependencies

9.1、依赖的方式

Gradle 中的依赖分别为直接依赖,项目依赖,本地jar 依赖。案例如下:

dependencies {
	//①.依赖当前项目下的某个模块[子工程]
	implementation project(':subject01')
	//②.直接依赖本地的某个jar文件
	implementation files('libs/foo.jar', 'libs/bar.jar')
	//②.配置某文件夹作为依赖项
	implementation fileTree(dir: 'libs', include: ['*.jar'])
	//③.直接依赖
	implementation 'org.apache.logging.log4j:log4j:2.17.2'
}

(1)直接依赖本地的某个jar文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

 //②.直接依赖本地的某个jar文件
    implementation files('libs/foo.jar', 'libs/bar.jar')
    implementation fileTree('dir':'libs',includes: ['*.jar'],excludes: ['.war'])

(2)依赖当前项目下的某个模块[子工程]

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

确保在settings.gradleinclude 'subproject01'

在这里插入图片描述
在这里插入图片描述

    //①.依赖当前项目下的某个模块[子工程]
    implementation project(':subproject01')

(3)直接依赖
直接依赖:依赖的类型 依赖的组名 依赖的名称 依赖的版本号

在这里插入图片描述

直接依赖:在项目中直接导入的依赖,就是直接依赖implementation 'org.apache.logging.log4j:log4j:2.17.2' 上面是简写法,完整版写法如下:

implementation  group: 'org.apache.logging.log4j', name: 'log4j', version: '2.17.2' 
group/name/version

共同定位一个远程仓库,version 最好写一个固定的版本号,以防构建出问题,implementation 类似
maven 中的依赖的scope,对比 maven 中的依赖:

<dependencies>
	<dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.12</version>
		<scope>compile</scope>
	</dependency>
</dependencies>

9.2、依赖的下载

当执行 build 命令时,gradle 就会去配置的依赖仓库中下载对应的 Jar,并应用到项目中。

9.3、依赖的类型

类似于 Maven 的 scope 标签,gradle 也提供了依赖的类型,具体如下所示:

类型介绍
compileOnly由java插件提供,曾短暂的叫provided,后续版本已经改成了compileOnly,适用于编译期需要而不需要打包的情况
runtimeOnly由 java 插件提供,只在运行期有效,编译时不需要,比如mysql 驱动包。,取代老版本中被移除的 runtime
implementation由 java 插件提供,针对源码[src/main 目录] ,在编译、运行时都有效,取代老版本中被移除的 compile
testCompileOnly由 java 插件提供,用于编译测试的依赖项,运行时不需要
testRuntimeOnly由 java 插件提供,只在测试运行时需要,而不是在测试编译时需要,取代老版本中被移除的testRuntime
testImplementation由 java 插件提供,针对测试代码[src/test 目录] 取代老版本中被移除的testCompile
providedCompilewar 插件提供支持,编译、测试阶段代码需要依赖此类jar 包,而运行阶段容器已经提供了相应的支持,所以无需将这些文件打入到war 包中了;例如servlet-api.jar、jsp-api.jar
compile编译范围依赖在所有的 classpath 中可用,同时它们也会被打包。在gradle 7.0 已经移除
apijava-library 插件提供支持,这些依赖项可以传递性地导出给使用者,用于编译时和运行时。取代老版本中被移除的 compile
compileOnlyApijava-library 插件提供支持,在声明模块和使用者在编译时需要的依赖项,但在运行时不需要。

官方文档参考:
https://docs.gradle.org/current/userguide/java_library_plugin.html#java_library_plugin:
各个依赖范围的关系和说明

https://docs.gradle.org/current/userguide/upgrading_version_6.html#sec:configuration_removal :
依赖范围升级和移除

https://docs.gradle.org/current/userguide/java_library_plugin.html#java_library_plugin
API 和implemention 区别

https://docs.gradle.org/current/userguide/java_plugin.html#java_plugin:
执行java 命令时都使用了哪些依赖范围的依赖。提示 1:java 插件提供的功能,java-library 插件都提供
在这里插入图片描述

9.4、api 与implementation 区别

如下所示:
在这里插入图片描述
编译时:如果 libC 的内容发生变化,由于使用的是 api 依赖,依赖会传递,所以 libC、libA、projectX 都要发生变化,都需要重新编译,速度慢,运行时:libC、libA、projectX 中的class 都要被加载。
编译时:如果libD 的内容发生变化,由于使用的是implemetation 依赖,依赖不会传递,只有libD、libB 要变化并重新编译,速度快,运行时:libC、libA、projectX 中的class 都要被加载。
拓展 3:api 和implementation 案例分析
在这里插入图片描述
api 的适用场景是多module 依赖,moduleA 工程依赖了 module B,同时module B 又需要依赖了 module C,modelA 工程也需要去依赖 module C,这个时候避免重复依赖module,可以使用 module B api 依赖的方式去依赖module C,modelA 工程只需要依赖 moduleB 即可。
总之,除非涉及到多模块依赖,为了避免重复依赖,咱们会使用api,其它情况我们优先选择implementation,拥有大量的api 依赖项会显著增加构建时间。

9.5、依赖冲突及解决方案

依赖冲突是指 “在编译过程中, 如果存在某个依赖的多个版本, 构建系统应该选择哪个进行构建的问题”,如下所示:
在这里插入图片描述
A、B、C 都是本地子项目 modulelog4j 是远程依赖。

编译时: B 用 1.4.2 版本的 log4j,C 用 2.2.4 版本的 log4j,B 和 C 之间没有冲突
打包时: 只能有一个版本的代码最终打包进最终的A对应的jar |war包,对于 Gradle 来说这里就有冲突了

依赖库
在这里插入图片描述

dependencies {
	testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' 
	testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' 
	implementation 'org.hibernate:hibernate-core:3.6.3.Final'
}

在这里插入图片描述
刷新上述内容后我们可以看到hibernate内依赖一个org.slf4j:slf4j-api:1.4.0

修 改 build.gradle

然后在系统当中引入implementation 'org.slf4j:slf4j-api:1.4.0'
在这里插入图片描述

dependencies {
	testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' 
	testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' 
	implementation 'org.hibernate:hibernate-core:3.6.3.Final' 
	implementation 'org.slf4j:slf4j-api:1.4.0'
}

刷新系统这时系统当中有两个相同的依赖
在这里插入图片描述
如上所示:

默认下,Gradle 会使用最新版本的 jar 包
【考虑到新版本的 jar 包一般都是向下兼容的】,实际开发中,还是建议使用官方自带的这种解决方案。

当然除此之外,Gradle 也为我们提供了一系列的解决依赖冲突的方法: exclude 移除一个依赖,不允许依赖传递,强制使用某个版本。

  • Exclude 排除某个依赖
    在这里插入图片描述
dependencies {
	testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' 
	testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' 
	implementation('org.hibernate:hibernate-core:3.6.3.Final'){
		//排除某一个库(slf4j)依赖:如下三种写法都行(选择其中一种)
		exclude group: 'org.slf4j' 
		exclude module: 'slf4j-api'
		exclude group: 'org.slf4j',module: 'slf4j-api'
	}
	//排除之后,使用手动的引入即可。
	implementation 'org.slf4j:slf4j-api:1.4.0'
}

hibernate当中的org.slf4j被排除
在这里插入图片描述

  • 不允许依赖传递
    在这里插入图片描述
dependencies {
	testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' 
	testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' 
	implementation('org.hibernate:hibernate-core:3.6.3.Final'){
		//不允许依赖传递,一般不用
		transitive(false)
	}
	//排除之后,使用手动的引入即可
	implementation 'org.slf4j:slf4j-api:1.4.0'
}

在这里插入图片描述
在添加依赖项时,如果设置 transitivefalse,表示关闭依赖传递。

即内部的所有依赖将不会添加到编译和运行时的类路径。

  • 强制使用某个版本!!
    在这里插入图片描述
    我们看到默认是最新版本

设置!!强制使用对应的版本

dependencies {
	testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' 
	testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' 
	implementation('org.hibernate:hibernate-core:3.6.3.Final')
	//强制使用某个版本!!【官方建议使用这种方式】
	implementation('org.slf4j:slf4j-api:1.4.0!!')
	//这种效果和上面那种一样,强制指定某个版本
	implementation('org.slf4j:slf4j-api:1.4.0'){
		version{
			strictly("1.4.0")
		}
	}
}

在这里插入图片描述

  • 拓展:我们可以先查看当前项目中到底有哪些依赖冲突:
    在这里插入图片描述
//下面我们配置,当 Gradle 构建遇到依赖冲突时,就立即构建失败
configurations.all() {
	Configuration configuration ->
	//当遇到版本冲突时直接构建失败
	configuration.resolutionStrategy.failOnVersionConflict()
}

在这里插入图片描述
在这里插入图片描述

9.6、设置依赖是最新版本(动态版本声明-不建议使用)(版本号用+代替或者latest:integration

在这里插入图片描述

 //设置最新版本
    implementation('org.slf4j:slf4j-api:+')

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

10、Gradle 插件

10.1、使用插件的原因

简单的说,通过应用插件我们可以:

  1. 促进代码重用、减少功能类似代码编写、提升工作效率
  2. 促进项目更高程度的模块化、自动化、便捷化
  3. 可插拔式的的扩展项目的功能

10.2、插件的作用

在项目构建过程中做很多事情,把插件应用到项目中,通常可以完成:
1、可以添加任务【task】到项目中,从而帮助完成测试、编译、打包等。
2、可以添加依赖配置到项目中。
3、可以向项目中拓展新的扩展属性、方法等。
4、可以对项目进行一些约定,如应用 Java 插件后,约定src/main/java 目录是我们的源代码存在位置,编译时编译这个目录下的Java 源代码文件。

10.3、插件的分类和使用

在这里插入图片描述

第一种:脚本插件

脚本插件的本质就是一个脚本文件,使用脚本插件时通过apply from:将脚本加载进来就可以了,后面的脚本文件可以是本地的也可以是网络上的脚本文件,下面定义一段脚本,我们在 build.gradle 文件中使用它,具体如下:

version.gradle文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ext {
    company= "itbluebox"
    cfgs = [
            compileSdkVersion : JavaVersion.VERSION_1_8
    ]
    spring = [
            version : '5.0.0'
    ]
}

下面将将在构建文件中使用这个脚本文件,具体如下:

build.gradle文件
在这里插入图片描述

//map作为参数
apply from :"version.gradle"
task taskVersion{
    doLast{
        println "name is :${company},JDK is ${cfgs.compileSdkVersion},code is ${spring.version}"
    }
}

运行
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
意义:脚本文件模块化的基础,可按功能把我们的脚本进行拆分一个个公用、职责分明的文件,然后在主脚本文件引用, 比如:将很多共有的库版本号一起管理、应用构建版本一起管理等。

第二种:对象插件之内部插件[核心插件]

二进制插件[对象插件]就是实现了 org.gradle.api.Plugin 接口的插件,每个 Java Gradle 插件都有一个 plugin id
在这里插入图片描述

(1)plugins DSL
在这里插入图片描述

plugins {
    id 'java'
}

(2)project.apply(apply:map具名参数方式)
key: plugin
value: 插件id,插件全类名、插件的简类名

可通过如下方式使用一个 Java 插件:

指定插件value,id的方式
在这里插入图片描述

apply plugin : 'java' //map

在这里插入图片描述
编译成功
在这里插入图片描述

具名参数方式或者:

//也可以使用闭包作为project.apply方法的一个参数
apply{
	plugin 'java'
}

通过上述代码就将 Java 插件应用到我们的项目中了,对于 Gradle 自带的核心插件都有唯一的 plugin id,其中 java 是Java 插件的 plugin id,这个 plugin id 必须是唯一的,可使用应用包名来保证 plugin id 的唯一性。这里的 java 对应的具体类型是 org.gradle.api.plugins.JavaPlugin,所以可以使用如下方式使用 Java 插件:
使用方式1:Map具名参数,全类名

在这里插入图片描述

apply plugin:org.gradle.api.plugins.JavaPlugin

org.gradle.api.plugins默认导入:

使用方式2
在这里插入图片描述

apply plugin: JavaPlugin

在这里插入图片描述

apply plugin: 'java' //核心插件,无需事先引入,

在这里插入图片描述

apply{
    plugin: 'java'
}

使用方式3:插件的id

Gradle 中提供的二进制插件【核心插件】,
可参考: https://docs.gradle.org/current/userguide/plugin_reference.html

第三种:对象插件之第三方插件

如果是使用第三方发布的二进制插件,一般需要配置对应的仓库和类路径,
在这里插入图片描述

//使用传统的应用方式
buildscript {
	ext {
		springBootVersion = "2.3.3.RELEASE"
	}
	repositories {
		mavenLocal()
		maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
		jcenter()
	}
	// 此处先引入插件
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}
//再应用插件
apply plugin: 'org.springframework.boot' //社区插件,需要事先引入,不必写版本号

但是如果是第三方插件已经被托管在
https://plugins.gradle.org/
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

网站上,就可以不用在 buildscript 里配置 classpath
依赖了,直接使用新出的 plugins DSL 的方式引用,案例如下: 使 用 plugins DSL 方 式

plugins {
	id 'org.springframework.boot' version '2.4.1'
}

注意:

  1. 如果使用老式插件方式buildscript{}要放在build.gradle 文件的最前面,而新式plugins{}没有该限制。
  2. 托管在网站gradle 插件官网的第三方插件有两种使用方式,一是传统的buildscript 方式,一种是 plugins DSL 方式 。
第四种:对象插件之用户自定义插件

参考官方文档
参考地址:https://docs.gradle.org/current/userguide/custom_plugins.html
在这里插入图片描述
在这里插入图片描述

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.task('hello') {
            doLast {
                println 'Hello from the GreetingPlugin'
            }
        }
    }
}

// Apply the plugin
apply plugin: GreetingPlugin

Output of gradle -q hello
在这里插入图片描述

> gradle -q hello

Hello from the GreetingPlugin

在这里插入图片描述

在这里插入图片描述

abstract class GreetingPluginExtension {
    abstract Property<String> getMessage()

    GreetingPluginExtension() {
        message.convention('Hello from GreetingPlugin')
    }
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Add the 'greeting' extension object
        def extension = project.extensions.create('greeting', GreetingPluginExtension)
        // Add a task that uses configuration from the extension object
        project.task('hello') {
            doLast {
                println extension.message.get()
            }
        }
    }
}

apply plugin: GreetingPlugin

// Configure the extension
greeting.message = 'Hi from Gradle'

在这里插入图片描述
Output of gradle -q hello

> gradle -q hello

Hi from Gradle

在这里插入图片描述
在这里插入图片描述

interface GreetingPluginExtension {
    Property<String> getMessage()
    Property<String> getGreeter()
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        def extension = project.extensions.create('greeting', GreetingPluginExtension)
        project.task('hello') {
            doLast {
                println "${extension.message.get()} from ${extension.greeter.get()}"
            }
        }
    }
}

apply plugin: GreetingPlugin

// Configure the extension using a DSL block
greeting {
    message = 'Hi'
    greeter = 'Gradle'
}

在这里插入图片描述

我们直接执行 hello 任务./gradle hello 即可,这种方式实现的插件我们一般不使用,
因为这种方式局限性太强,只能本Project,而其他的Project 不能使用

10.3、buildSrc 项目(自定义插件-本项目当中使用)

buildSrc 是Gradle 默认的插件目录,编译 Gradle 的时候会自动识别这个目录,将其中的代码编译为插件。

  1. 首先先建立一个名为 buildSrcjava Module,
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    创建成功
    在这里插入图片描述
    buildSrcincluded modules 移除,
    在这里插入图片描述

重新构建
在这里插入图片描述

然后只保留 build.gradlesrc/main 目录,
在这里插入图片描述
在这里插入图片描述

其他全部删掉,注意名字一定是 buildSrc,不然会找不到插件。

  1. 然后修改Gradle 中的内容
    在这里插入图片描述
apply plugin: 'groovy' // 必 须
apply plugin: 'maven-publish'

dependencies {
    implementation gradleApi() //必须
    implementation localGroovy() //必须
}

repositories {
    google()
    jcenter()
    mavenCentral() //必须
}

//把项目入口设置为src/main/groovy
sourceSets {
    main {
        groovy {
            srcDir 'src/main/groovy'
        }
    }
}
  1. 创建入口目录,在src/main 下创建代码入口目录,如下:
  2. 然后实现插件代码Text.groovy,注意文件后缀为groovy,文件要引入package com.itbluebox
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

import org.gradle.api.Plugin
import org.gradle.api.Project
class Text implements Plugin<Project>{
    @Override
    void apply(Project project) { project.task("itbluebox"){
            doLast{
                println("自定义itbluebox插件")
            }
        }
    }
}

接下来在 main 目录下创建
resources 目录,
在 resources 目录下创建 META-INF 目录,
在 META-INF 目录下创建
gradle-plugins 目录,在gradle-plugins 目录下创建properties 文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
properties 文件可以自己命名,

但是要以.properties 结尾,

比如

com.itbluebox.plugin.properties,

com.itbluebox.plugin 就是定义的包名路径

在这里插入图片描述

最后需要在properties 文件中指明我们实现插件的全类名

implementation-class=com.itbluebox.Text

到目前为止我们的插件项目已经写完了,

在这里插入图片描述
module 引入我们写的插件
apply plugin:'com.itbluebox.plugin',然后执行插件的Task,gradle itbluebox
在这里插入图片描述

这种形式的写法,在我们整个工程的module 都可以使用,但也只是限制在本工程,其他工程不能使用。

10.4、自定义插件-多个工程使用

第二种写插件的方式他只能在本工程中使用,
而其他的项目工程不能使用,

有时候我们需要一个插件在多个工程中使用,
这时候我们就需要把插件上传maven 中。

第一步: 首先将上述buildSrc 目录复制一份,修改文件夹名,

在这里插入图片描述

然后在settings.gradle 文件中使用include
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

引入第二步:修改build.gradle 文件,发布到maven 仓库中

在这里插入图片描述

apply plugin: 'groovy' // 必 须
apply plugin: 'maven-publish'

dependencies {
    implementation gradleApi() //必须
    implementation localGroovy() //必须
}

repositories {
    google()
    jcenter()
    mavenCentral() //必须
}

//把项目入口设置为src/main/groovy
sourceSets {
    main {
        groovy {
            srcDir 'src/main/groovy'
        }
    }
}

publishing {
    publications {
        myLibrary(MavenPublication) {
            groupId = 'com.itbluebox.plugin' //指定GAV坐标信息
            artifactId = 'library'
            version = '1.1'
            from components.java//发布jar包
            //from components.web///引入war插件,发布war包
        }
    }
    repositories {
        maven { url "$rootDir/lib/release" }
        //发布项目到私服中
        //	maven {
        //	name = 'myRepo' //name属性可选,表示仓库名称,url必填
        //	//发布地址:可以是本地仓库或者maven私服
        //	//url = layout.buildDirectory.dir("repo")
        //	//url='http://my.org/repo'
        //	// change URLs to point to your repos, e.g. http://my.org/repo
        //	//认证信息:用户名和密码
        //	credentials {
        //	username = 'joe'
        //	password = '****'
        //	}
        //	}
    }
}

在这里插入图片描述
在这里插入图片描述
设置多个组件
在这里插入图片描述

  aaaa(MavenPublication) {
            groupId = 'com.itbluebox.plugin' //指定GAV坐标信息
            artifactId = 'library'
            version = '1.1'
            from components.java//发布jar包
            //from components.web///引入war插件,发布war包
        }

在这里插入图片描述
在这里插入图片描述

第三步:执行publish 指令,发布到根 project 或者maven 私服仓库。

在这里插入图片描述
在这里插入图片描述

第四步:使用插件,在项目级 build.gradle 文件中将插件添加到 classpath:

在这里插入图片描述

buildscript {
	repositories {
		maven { url "$rootDir/lib/release" }
	}
	dependencies {
		classpath "com.itbluebox.plugin:library:1.1"
	}
}

apply plugin: 'java'
//是在 itblueboxplugin  中定义的插件 ID 
apply plugin: 'com.itbluebox.plugin'
第五步:执行 gradle build 指令就会在控制台看到自定义插件的输出,说明自定义插件就已经生效了。

最后,至于如何写一个插件,能帮助项目更加自动化或者便捷化,是值得大家未来需要长期思考、关注、努力的点。

10.5、插件的关注点

第一点: 插件的引用
apply plugin: '插件名'
第二点:主要的功能[任务]

在这里插入图片描述

当我们在工程中引入插件后,
插件会自动的为我们的工程添加一些额外的任务来完成相应的功能。

以Java 插件为例,当我们加入java 插件之后,就加入了如下功能:
具体大家可通过gradle tasks 查看加入某个插件前后的区别。

说明:Gradle 中的任务依赖关系是很重要的,
它们之间的依赖关系就形成了构建的基本流程。
第三点:工程目录结构
在这里插入图片描述
一些插件对工程目结构有约定,所以我们一般遵循它的约定结构来创建工程,这也是 Gradle 的“约定优于配置”原则。例如java 插件规定的项目源集目录结构如下所示:
如果要使用某个插件就应该按照它约定的目录结构设置,这样能大大提高我们的效率,当然各目录结构也可以自己定义。

第四点:依赖管理

比如前面我们提到的 依赖的类型[依赖管理]部分,不同的插件提供了不同的依赖管理。

第五点:常用的属性

例如:Java 插件会为工程添加一些常用的属性,我们可以直接在编译脚本中直接使用。
在这里插入图片描述
当然还有一些其他属性

在这里插入图片描述

10.6、Java 插件分析

参考官网:https://docs.gradle.org/current/userguide/plugin_reference.html,
以Java 插件为例,讲解需要关注的几点:
在这里插入图片描述
在这里插入图片描述

第一点:我们要关注插件使用

plugins {
	id 'java'
}

第二点:我们要关注插件的功能
我们可通过官方文档介绍了解某个插件功能或者百度、再或者大家可以通过 gradle tasks 查看加入java 插件前后的区别。
第三点:项目布局
一般加入一个插件之后,插件也会提供相应的目录结构,例如:java 插件的目录结构

在这里插入图片描述
当然这个默认的目录结构也是可以改动的例如:
在这里插入图片描述

sourceSets {
    main {
        java {
            srcDirs = ['src/itbluebox/java']
        }
        resources {
            srcDirs = ['src/itbluebox/resources']
        }
    }
}

在这里插入图片描述
main 目录不高亮
在这里插入图片描述
也可以设置针对test目录
在这里插入图片描述

test {
        java {
            srcDirs = ['src/bbb/java']
        }
        resources {
            srcDirs = ['src/bbb/resources']
        }
    }

在这里插入图片描述
在这里插入图片描述
test的目录的高亮也消失了
在这里插入图片描述

可以手动创建对应标准的目录结构
在这里插入图片描述
在这里插入图片描述
全选
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
修改编译后文件输出目录结构
在这里插入图片描述

output.resourcesDir = file('out/bin');

java.destinationDirectory.set(file('out/bin'))

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

指定源码和字节码
在这里插入图片描述

sourceCompatibility(JavaVersion.VERSION_1_8)
targetCompatibility(JavaVersion.VERSION_1_8)

也可设置源集的属性等信息。
在这里插入图片描述
第四点:依赖管理:以java 插件为例,提供了很多依赖管理项
源集依赖关系配置
在这里插入图片描述
测试源集依赖关系配置第五点:额外的属性和方法:
可参考官方文档: sourceCompatibility(JavaVersion.VERSION_1_8)

10.7、build.gradle 文件

build.gradle 是一个gradle 的构建脚本文件,支持java、groovy 等语言。

● 每个project 都会有一个build.gradle 文件,该文件是项目构建的入口,可配置版本、插件、依赖库等信息。

● 每个build 文件都有一个对应的 Project 实例,对build.gradle 文件配置,本质就是设置Project 实例的属性和方法。

● 由于每个 project 都会有一个build 文件,
那么Root Project 也不列外.Root Project 可以获取到所有 Child Project,
所以在Root Project 的 build 文件中我们可以对Child Project 统一配置,比如应用的插件、依赖的maven 中心仓库等。
在这里插入图片描述
build 文件中常见的属性和方法如下所示:

10.8、常见属性代码

代码参考:

//指定使用什么版本的JDK语法编译源代码,跟编译环境有关,在有java插件时才能用
sourceCompatibility = 1.8
//指定生成特定于某个JDK版本的class文件:跟运行环境有关,在有java插件时才能用
targetCompatibility = 1.8
//业务编码字符集,注意这是指定源码解码的字符集[编译器] 
compileJava.options.encoding "UTF-8"
//测试编码字符集,注意这是指定源码解码的字符集[编译器] 
compileTestJava.options.encoding "UTF-8"
//编译JAVA文件时采用UTF-8:注意这是指定源码编码的字符集【源文件】
tasks.withType(JavaCompile) {
	options.encoding = "UTF-8"
}
//编译JAVA文件时采用UTF-8:注意这是指定文档编码的字符集【源文件】
tasks.withType(Javadoc) {
	options.encoding = "UTF-8"
}

提示 1:group+name+version 类似于 mavengroup+artifactId+version
提示 2:encoding 解决业务代码与测试代码中文乱码问题

10.9、Repositories(配置依赖仓库)

在这里插入图片描述

repositories {
	//gradle中会按着仓库配置的顺序,从上往下依次去对应的仓库中找所需要的jar包:
	//如果找到,则停止向下搜索,如果找不到,继续在下面的仓库中查找
	//指定去本地某个磁盘目录中查找:使用本地file文件协议:一般不用这种方式
	maven { url 'file:///D:/repos/mavenrepos3.5.4'} 
	maven { url "$rootDir/lib/release" }
	
	//指定去maven的本地仓库查找
	mavenLocal()
	//指定去maven的私服或者第三方镜像仓库查找
	maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" } 
	maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" }
	//指定去maven的远程仓库查找:即 https://repo.maven.apache.org/maven2/
	mavenCentral()
	//去google仓库查找
	google()
}

10.10、Subprojects 与 Allprojects

allprojects
是对所有project(包括Root Project+ child Project[当前工程和所有子工程])
的进行统一配置,

在这里插入图片描述

allprojects {
	tasks.create('hello') { 
		doLast {
			task ->
			println "project name is $task.project.name"
		}
	}
}
gradle clean
gradle build

subprojects
是对所有Child Project 的进行统一配置。测试如下:

subprojects {
	hello.doLast{ 
		task->
		println "here is subprojects $task.project.name"
	}
}

通常在 subprojectsallprojects 中:

allprojects(){ //本质Project中的allprojects方法,传递一个闭包作为参数。
	apply plugin: 'java'
	ext {
		junitVersion = '4.10'
		..
	}
	task allTask{
	...
	}
	repositories {
	...
	}
	dependencies {
	...
	}
}
subprojects(){//同上面allprojects中的方法。
}

拓展 1: 如果是直接在根project 配置 repositoriesdependencies 则只针对根工程有效。
拓展:我们也可以在对单个 Project 进行单独配置:

project('subject01') {
	task subject01 {
		doLast {
			println 'for subject01'
		}
	}
}

执行gradle build 指令即可查看测试效果。

10.11、ext 用户自定义属性

Project 和 Task 都允许用户添加额外的自定义属性,要添加额外的属性,通过应用所属对象的ext 属性即可实现。

添加之后可以通过 ext 属性对自定义属性读取和设置,如果要同时添加多个自定义属性,可以通过 ext 代码块:
在这里插入图片描述

//自定义一个Project的属性
ext.age = 18
//通过代码块同时自定义多个属性
ext {
	phone = 19292883833
	address="itbluebox"
}
task extCustomProperty {
	//在task中自定义属性
	ext {
		desc = "奥利给"
	}
	doLast {
		println " 年 龄 是 :${age}" 
		println "电话是:${phone}" 
		println "地址是:${address}" 
		println "itbluebox:${desc}"
	}
}

测试:通过 gradle extCustomProperty
输出结果为:
在这里插入图片描述
拓展 1: ext 配置的是用户自定义属性,而gradle.properties 中一般定义 系统属性、环境变量、项目属性、JVM 相关配置信息。
例如
gradle.properties 文件案例:加快构建速度的,
gradle.properties 文件中的属性会自动在项目运行时加载。
在这里插入图片描述
在这里插入图片描述

设置此参数主要是编译下载包会占用大量的内存,可能会内存溢出
在这里插入图片描述

org.gradle.jvmargs=-Xms4096m -Xmx8192m 
# 开启gradle缓存
org.gradle.caching=true 
# 开启并行编译
org.gradle.parallel=true
# 启用新的孵化模式
org.gradle.configureondemand=true 
# 开启守护进程
org.gradle.daemon=true

详细请参考:https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties

10.12、Buildscript

buildscript 里是gradle 脚本执行所需依赖,分别是对应的 maven 库和插件。案例如下:

import org.apache.commons.codec.binary.Base64 
buildscript {
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath group: 'commons-codec', 
		name: 'commons-codec', 
		version: '1.2'
	}
}
tasks.register('encode')
 { 
	 doLast {
		def byte[] encodedString = new Base64().encode('hello world\n'.getBytes()) 
		println new String(encodedString)
	}
}

需要注意的是:
1. buildscript{}必须在 build.gradle 文件的最前端。
2. 对于多项目构建,项目的 buildscript ()方法声明的依赖关系可用于其所有子项目的构建脚本。
3. 构建脚本依赖可能是 Gradle 插件。

案例如下所示:

//老式apply插件的引用方式,使用apply+buildscript
buildscript { 
	ext {
		springBootVersion = "2.3.3.RELEASE"
	}
	repositories {
		mavenLocal()
		maven { 
			url 'http://maven.aliyun.com/nexus/content/groups/public' 
		} 
		jcenter()
	}
	//此处引入插件
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}
apply plugin: 'java' //核心插件,无需事先引入
apply plugin: 'org.springframework.boot' //社区插件,需要事先引入,才能应用,不必写版本号

11、publishing 项目发布

接下来,将咱们写好的模块发布发布到公司的私服以供别人使用,如下所示:
在这里插入图片描述

11.1、引入maven 发布的插件

在这里插入图片描述

plugins {
	//id 'java-library' //如果发布war包,需要war插件,java-library支持带源码、文档发布
	id 'maven-publish'
}

11.2、设置发布代码

在这里插入图片描述

//带源码和javadoc的发布:需要'java-library'插件支持:它是java的升级版,java插件的功能java-library都有
//javadoc.options.encoding="UTF-8"
//java {
//	withJavadocJar()
//	withSourcesJar()
//} 
publishing {
	publications {
		myLibrary(MavenPublication) {
			groupId = 'org.gradle.sample' //指定GAV坐标信息artifactId = 'library'
			version = '1.1'
			from components.java//发布jar包
			//from components.web///引入war插件,发布war包
		}
	}
	repositories {
		//本地仓库位于USER_HOME/.m2/repository mavenLocal()
		//发布项目到私服中
		maven {
			name = 'myRepo' //name属性可选,表示仓库名称,url必填
			//发布地址:可以是本地仓库或者maven私服
			//url = layout.buildDirectory.dir("repo")
			// change URLs to point to your repos, e.g. http://my.org/repo
			def releasesRepoUrl = layout.buildDirectory.dir('repos/releases')
			def snapshotsRepoUrl = layout.buildDirectory.dir('repos/snapshots')
			url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
			//认证信息:用户名和密码
			//	credentials {
			//	username = 'joe'
			//	password = '****'
			//	}
		}
	}
}

11.3、执行发布指令

执 行 发 布 命 令 , 将 项 目 发 布 到 本 地 仓 库 或 者 远 程 仓 库 。

常 见 的 发 布 指 令 有 :
generatePomFileForPubNamePublication: 生成 pom 文件
publishPubNamePublicationToRepoNameRepository:发布项目到指定仓库,如果没有仓库名,默认为maven
publishPubNamePublicationToMavenLocal: 将 PubName 发布复制到本地 Maven 仓库中包括POM 文件和其他元数据。

publish: 发布到 repositories 中指定的仓库(为比如 Maven 私服)

publishToMavenLocal: 执行所有发布任务中的操作发布到本地 maven 仓库
【默认在用户家目录下的 .m2/repository】。
在这里插入图片描述
在这里插入图片描述
发布成功
在这里插入图片描述

发布war包
在这里插入图片描述

apply plugin: 'war'

在这里插入图片描述

from components.web///引入war插件,发布war包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
带源码和javadoc的发布

在这里插入图片描述

//带源码和javadoc的发布:需要'java-library'插件支持:它是java的升级版,java插件的功能java-library都有
javadoc.options.encoding="UTF-8"
java {
	withJavadocJar()
	withSourcesJar()
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

12、生命周期中Hook

生命周期中的这些钩子函数都是由 gradle 自动回调完成的,
利用这些钩子函数可以帮助我们实现一些我们想要的功能。
在这里插入图片描述
Gradle 在生命周期各个阶段都提供了用于回调的钩子函数:
Gradle 初始化阶段:
● 在 settings.gradle 执行完后,会回调 Gradle 对象的 settingsEvaluated 方法
● 在构建所有工程 build.gradle 对应的Project 对象后,也既初始化阶段完毕,会回调 Gradle 对象的projectsLoaded 方法
Gradle 配置阶段:
● Gradle 会循环执行每个工程的 build.gradle 脚本文件
● 在执行当前工程build.gradle 前,会回调Gradle 对象的 beforeProject 方法和当前Project 对象的 beforeEvaluate 方法, 虽然 beforeEvalute 属于 project 的生命周期, 但是此时 build script 尚未被加载, 所以 beforeEvaluate 的设置依 然要在 init script 或 setting script 中进行,不要在 build script 中使用 project.beforeEvaluate 方法。
● 在执行当前工程 build.gradle 后,会回调 Gradle 对象的afterProject 方法和当前Project 对象的 afterEvaluate 方法
● 在所有工程的 build.gradle 执行完毕后,会回调 Gradle 对象的 projectsEvaluated 方法
● 在构建 Task 依赖有向无环图后,也就是配置阶段完毕,会回调TaskExecutionGraph 对象的 whenReady 方法
Gradle 执行阶段:
● Gradle 会循环执行Task 及其依赖的 Task
● 在当前 Task 执行之前,会回调 TaskExecutionGraph 对象的 beforeTask 方法
● 在当前 Task 执行之后,会回调 TaskExecutionGraph 对象的 afterTask 方法当所有的 Task 执行完毕后,会回调 Gradle 对象的 buildFinish 方法。

提示:Gradle 执行脚本文件的时候会生成对应的实例,主要有如下几种对象:
1、Gradle 对象:在项目初始化时构建,全局单例存在,只有这一个对象
2、Project 对象:每一个build.gradle文件 都会转换成一个 Project 对象,类似于maven中的pom.xml文件
3、Settings 对象:settings.gradle 会转变成一个 settings 对象,和整个项目是一对一的关系,一般只用到include方法
4.、Task对象: 从前面的有向无环图中,我们也可以看出,gradle最终是基于Task的,一个项目可以有一个或者多个Task
钩子函数代码演示:项目目录结构如下:
在这里插入图片描述
在root project 的settings.gradle 文件中添加:
在这里插入图片描述

gradle.settingsEvaluated { //1.settingsEvaluated钩子函数,在初始化阶段完成
	println "settingsEvaluated"
}
gradle.projectsLoaded { //2.projectsLoaded钩子函数,在初始化阶段完成
	println "projectsLoaded"
}
//声明一个变量:表示当前项目名,在每次执行某个项目的beforeEvaluate方法时先给projectName变量赋值
//这样方便在:gradle.beforeProject和afterProject两个钩子函数使用。
def projectName=""
gradle.addProjectEvaluationListener(  new ProjectEvaluationListener(){
	//3.执行各个project的beforeEvaluate:在配置阶段完成@Override
	void beforeEvaluate(Project project) 
	{ 
	projectName=project.name
	println "${project.name} Project beforeEvaluate"
	}
	//5.执行各个project的afterEvaluate:在配置阶段完成@Override
	void afterEvaluate(Project project, ProjectState projectState) { 
	println "${project.name} Project afterEvaluate"
	}
});
gradle.beforeProject {
	//4.执行各个project的beforeProject:在配置阶段完成
	println "${projectName} beforeProject..."
}
gradle.afterProject {
	//6.执行各个project的afterProject:在配置阶段完成
	println "${projectName} afterProject..."
}
//7.所有工程的 build.gradle 执行完毕后,回调 Gradle 对象的 projectsEvaluated 方法:在配置阶段完成
def rootProjectName=rootProject.getName() 
gradle.projectsEvaluated {
	println "${rootProjectName} projectsEvaluated..."
}
//8.配置阶段完毕后,回调 TaskExecutionGraph 对象的 whenReady 方法:在配置阶段完成
gradle.taskGraph.whenReady {
	println "${rootProjectName} taskGraph whenReady..."
}

//9.在当前Task执行之前,会回调 TaskExecutionGraph 对象的 beforeTask方法:在执行阶段完成
gradle.taskGraph.beforeTask { task ->
	println "this is the task ${task.name} of the project ${task.getProject().name} beforeTask.."
}
//10.在当前Task执行之后,会回调 TaskExecutionGraph 对象的 afterTask方法:在执行阶段完成
gradle.taskGraph.afterTask { task ->
	println "this is the task ${task.name} of the project ${task.getProject().name}  afterTask.."
}
//11.当所有的 Task 执行完毕后,会回调 Gradle 对象的 buildFinish 方法:在执行阶段完成
gradle.buildFinished {
	println "${rootProjectName} buildFinished..."
}

在root 的build.gradle 文件中添加:

task A {
	println "root taskA" 
	doFirst(){
		println "root taskA doFirst"
	}
	doLast(){
		println "root taskA doLast"
	}
}

在subject01 的 build.gradle 文件中添加:


task B {
	println "SubProject01 taskB" 
	doFirst(){
	println "SubProject01 taskB doFirst"
}
doLast(){
	println "SubProject01 taskB doLast"
	}
}

在subject02 的 build.gradle 文件中添加:

//task C 在上面
task C{
// 依赖task D
	dependsOn 'D'
	println "SubProject02 taskC" 
	doFirst(){
		println "SubProject02 taskC doFirst"
	}
	doLast(){
		println "SubProject02 taskC doLast"
	}
}

//task D 在下面

task D {
	println "SubProject02 taskD" 
	doFirst(){
		println "SubProject02 taskD doFirst"
	}
	doLast(){
		println "SubProject02 taskD doLast"
	}
}

测试:在root 工程的根目录执行:
gradle C .就能看到 gradle 生命周期的三个阶段,
及每个阶段执行的钩子函数、
还有在执行阶段有依赖关系的任务的执行顺序问题。

拓展 1:在settings.gradle 中添加监听器,查看task 有向无环图:

gradle.taskGraph.addTaskExecutionGraphListener(new TaskExecutionGraphListener() { 
	@Override // 生成有向无环图
	void graphPopulated(TaskExecutionGraph taskExecutionGraph) { 	
		taskExecutionGraph.allTasks.forEach(task->{//核心逻辑:通过taskExecutionGraph获得所有的task
		taskExecutionGraph.allTasks.forEach(releaseTask->{
			println "itbluebox:" + releaseTask.getProject().name + ":" + releaseTask.name
			})
		})
	}
})

测试:在root 工程根目录下执行:gradle C。查看测试结果:
拓展 2: 计算 Gradle 构建过程中各个阶段的耗时:需要注意,这里只是计算了初始化阶段的 settings 文件,并没有计算init.gradle 初始化的时间。

def projectName=rootProject.getName() //定义项目名
long beginOfSetting = System.currentTimeMillis() //初始化阶段开始时间
def beginOfConfig // 配置阶段开始时间
def configHasBegin = false //配置阶段是否开始了,只执行一次
def beginOfProjectConfig = new HashMap() //存放每个build.gradle 执行之前的时间
def beginOfTaskExecute // 执行阶段开始时间
gradle.projectsLoaded { // 初始化阶段执行完毕
	println "${projectName}工程 初始化总耗时  ${System.currentTimeMillis() - beginOfSetting} ms"
}
//build.gradle 执行前
gradle.beforeProject { Project project -> 
	if(!configHasBegin){
		configHasBegin = true
		beginOfConfig = System.currentTimeMillis()
	}
	beginOfProjectConfig.put( project, System.currentTimeMillis())
}
//build.gradle 执行后
gradle.afterProject { Project project ->
	def begin = beginOfProjectConfig.get(project)
	if(project.name == projectName) {
		println "根工程${projectName} 配置阶段耗时:${System.currentTimeMillis() - begin} ms"
	}else{
		println "子工程${project.name} 配置阶段耗时:${System.currentTimeMillis() - begin} ms"
	}
}
gradle.taskGraph.whenReady {
	//配置阶段完毕
	println "整个${projectName}项目在配置阶段总耗时:${System.currentTimeMillis() - beginOfConfig} ms"
	beginOfTaskExecute = System.currentTimeMillis()
}
//执行阶段开始
gradle.taskGraph.beforeTask {Task task ->
	task.doFirst {
		task.ext.beginOfTask = System.currentTimeMillis()
	}
	task.doLast {
		println "${task.name}在执行阶段耗时:${System.currentTimeMillis() - task.ext.beginOfTask} ms"
	}
}
gradle.buildFinished {//执行阶段完毕
	println " 执行阶段总耗时:${System.currentTimeMillis() - beginOfTaskExecute} ms"
	println " 整个构建过程耗时:${System.currentTimeMillis() - beginOfSetting} ms"
}
Gradle文章目录
Java之Gradle【IDEA版】入门到精通(上)(一篇文章精通系列)【安装+基本使用+项目创建+项目部署+文件操作+依赖管理+插件使用】
Java之Gradle【IDEA版】入门到精通(下)(一篇文章精通系列)【创建 Springboot 项目+基于 ssm 多模块项目案例+微服务实战】
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员猫爪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值