Hello World

新建项目

直接在线新建: https://start.spring.io/

Gradle Spring Boot_kotlin

然后对比本地的区别, 修改 build.gradle.kts

编码问题

参考: Gradle项目中文乱码的解决办法

打包问题

参考 spring boot 插件官网: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/

build.gradle.kts

import org.springframework.boot.gradle.tasks.bundling.BootJar

plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    application
    java
    id("org.springframework.boot") version "2.7.13"
    id("io.spring.dependency-management") version "1.0.15.RELEASE"
}

repositories {
    maven("https://maven.aliyun.com/repository/public/")
    maven("https://maven.aliyun.com/repository/spring/")
    mavenLocal()
    mavenCentral()
}

dependencies {
    // test
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.testng:testng:7.5")
    testImplementation("org.hamcrest:hamcrest-all:1.3")

    // spring boot
    implementation("org.springframework.boot:spring-boot-starter")
    implementation("org.springframework.boot:spring-boot-starter-web")

    // tool
    implementation("cn.hutool:hutool-all:5.0.1")
    implementation("com.google.guava:guava:31.1-jre")
    implementation("org.apache.commons:commons-lang3")
    implementation("org.mapstruct:mapstruct-jdk8:1.4.2.Final")
    implementation("org.mapstruct:mapstruct-processor:1.4.2.Final")

    // lombok
    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")
}

// 项目坐标
group = "com.laolang.shop"
version = "1.0"

// Apply a specific Java toolchain to ease working on different environments.
java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(8))
    }
}

application {
    // 启动类
    mainClass.set("com.laolang.shop.ShopApplication")
}

tasks.named<Test>("test") {
    // Use TestNG for unit tests.
    useTestNG()
}

tasks.withType<Test> {
    this.testLogging {
        this.showStandardStreams = true
    }
}

// UTF-8 编码
tasks.withType<JavaCompile>{
    options.encoding = "UTF-8"
}

// spring boot 插件打包
tasks.named<BootJar>("bootJar"){
    // jar 包名称
    archiveBaseName.set("boot-shop")
    // 版本号设置为空
    archiveVersion.set("")
}


运行

可以使用 gradle run 运行, 也可以使用spring boot 的插件的方式

app 为项目目录

gradle app:bootRun

打包

直接执行命令即可

app 为项目目录

gradle app:bootJar

也可以使用 idea 

Gradle Spring Boot_kotlin_02


分离 jar 包和配置文件

Gradle+bootJar打包SpringBoot工程并分离jar包和配置文件


关于 gradle 和 spring boot 之间的版本问题

使用 spring initializr 创建的项目会使用比较新的 spring boot 版本, 如果想要使用比价旧的 spring boot 版本, 那么就要和 gradle 版本对应, 比如上面的项目使用的 spring boot 版本为 2.7, 如果我切换到2.2, 那么最好也把 wrapper 版本改一下

https://docs.spring.io/spring-boot/docs/2.2.13.RELEASE/gradle-plugin/reference/html/

Gradle Spring Boot_kotlin_03

除了 org.springframework.boot 之外, 还需要 io.spring.dependency-management , 在文档中可以搜到

Gradle Spring Boot_kotlin_04

否则的话会有问题

Gradle Spring Boot_kotlin_05


按照官网提示, 2.2.13.RELEASE 需要 6.x 的 gradle,  在 https://gradle.org/releases/ 找一个符合

Gradle Spring Boot_sprin boot_06

然后修改 wrapper

Gradle Spring Boot_gradle_07


Gradle Spring Boot_kotlin_08

此时依然有报错

Gradle Spring Boot_kotlin_09

注释即可

现在就没有问题了, build.gradle.kts 内容如下

import org.springframework.boot.gradle.tasks.bundling.BootJar

plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    application
    java
    id("org.springframework.boot") version "2.2.13.RELEASE"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
}

// 项目坐标
group = "com.laolang.shop"
version = "1.0"

// spring boot 插件打包
tasks.named<BootJar>("bootJar") {
    // jar 包名称
    archiveBaseName.set("boot-shop")
    // 版本号设置为空
    archiveVersion.set("")
}

application {
    // 启动类
    mainClass.set("com.laolang.shop.ShopApplication")
}

tasks.named<Test>("test") {
    // Use TestNG for unit tests.
    useTestNG()
}

tasks.withType<Test> {
    this.testLogging {
        this.showStandardStreams = true
    }
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

// UTF-8 编码
tasks.withType<JavaCompile> {
    options.encoding = "UTF-8"
}


dependencies {
    // test
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.testng:testng:7.5")
    testImplementation("org.hamcrest:hamcrest-all:1.3")

    // spring boot
    implementation("org.springframework.boot:spring-boot-starter")
    implementation("org.springframework.boot:spring-boot-starter-web")

    // 数据库
    implementation("com.baomidou:mybatis-plus-boot-starter:3.5.1")
    implementation("com.alibaba:druid-spring-boot-starter:1.2.4")
    implementation("com.github.pagehelper:pagehelper-spring-boot-starter:1.4.0")
    runtimeOnly("mysql:mysql-connector-java")

    // tool
    implementation("cn.hutool:hutool-all:5.0.1")
    implementation("com.google.guava:guava:23.0")
    implementation("org.apache.commons:commons-lang3")


    // lombok
    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")
}

repositories {
    maven("https://maven.aliyun.com/repository/public/")
    maven("https://maven.aliyun.com/repository/spring/")
    mavenLocal()
    mavenCentral()
}

然后使用 gradlew 来运行和打包即可

Gradle Spring Boot_gradle_10

Gradle Spring Boot_sprin boot_11


聚合项目 && 多模块

注意事项

  1. 最新版 8.1 没有成功, 用的 6.9.4 版本
  2. 注意 lombok , 要针对程序本身和测试分别设置
  3. spring boot 版本为 2.2.13.RELEASE , 其他版本可能会有问题, 比如 spring-boot 插件和 gradle 插件不兼容, 具体解决办法见上文, 目前的办法是先用 gradle 6.9.4 和 spring boot 2.x 配合使用, 后续再用最新版本的 gradle 结合 gradlew 解决这个问题

目录结构

Gradle Spring Boot_gradle_12

common 是最底层的依赖

api 定义了各个模块的  Entity , Mapper , Service

biz 定义了各个模块的 Controller

starter 定义了自动类和所有的配置

如果模块间相互依赖, 比如 order 模块依赖了 product 模块, 就在 product-api 中添加一个 business 类, 然后 order 依赖 product-api 即可, 当然也免不了循环依赖, 这个时候可以 product-biz 依赖 product-api和order-api, order-biz 也是一样, 这样可以避免循环依赖, 当然也可以上 MQ

然后再把所有的 biz 都加入到 starter 就可以了

顶层 Gradle 脚本

settings.gradle.kts

指定根项目, 加入各个子模块

rootProject.name = "boot-shop"
include(":boot-shop-starter")
include(":boot-shop-common")
include(":boot-shop-admin")
include(":boot-shop-admin:boot-shop-admin-api")
include(":boot-shop-admin:boot-shop-admin-biz")

build.gradle.kts

依赖统一管理略坑, 暂无更好的办法

plugins {
    id("org.springframework.boot") version "2.2.13.RELEASE"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
}

group = "com.laolang.shop"
version = "1.0"

allprojects {
    repositories {
        maven("https://maven.aliyun.com/repository/public/")
        maven("https://maven.aliyun.com/repository/spring/")
        mavenLocal()
        mavenCentral()
        mavenCentral()
    }


    tasks.withType<JavaCompile> {
        options.encoding = "UTF-8"
        sourceCompatibility = "1.8"
        targetCompatibility = "1.8"
    }

    tasks.withType<Test>{
        useTestNG()
    }
}

// 定义依赖版本
configure<ExtraPropertiesExtension>{
    set("testngVersion","7.5")
    set("hamcrestVersion","1.3")

    set("mybatisPlusVersion","3.5.1")
    set("pagehelperVersion","1.2.4")
    set("druidVersion","1.4.0")

    set("hutoolVersion","5.0.1")
    set("guavaVersion","23.0")
}

starter Gradle 脚本

import org.springframework.boot.gradle.tasks.bundling.BootJar

plugins {
    id("java")
    id("org.springframework.boot")
    id("io.spring.dependency-management")
}

val testngVersion: String by rootProject.extra
val hamcrestVersion: String by rootProject.extra

dependencies {
    // 测试
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.testng:testng:7.5")
    testImplementation("org.hamcrest:hamcrest-all:1.3")

    // mysql
    runtimeOnly("mysql:mysql-connector-java")

    // 模块
    implementation(project(":boot-shop-admin:boot-shop-admin-biz"))

    // lombok
    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")
    testCompileOnly("org.projectlombok:lombok")
    testAnnotationProcessor("org.projectlombok:lombok")
}

// 打包
tasks.named<BootJar>("bootJar") {
    mainClassName = "com.laolang.shop.ShopApplication"
    archiveBaseName.set("boot-shop")
    archiveVersion.set("")
}

common Gradle 脚本

plugins {
    id("java-library")
    id("org.springframework.boot")
    id("io.spring.dependency-management")
}
 
// 引用顶层 build.gradle.kts 中 configure<ExtraPropertiesExtension> 定义的依赖版本号
val hutoolVersion: String by rootProject.extra
val mybatisPlusVersion: String by rootProject.extra
val pagehelperVersion: String by rootProject.extra
val druidVersion: String by rootProject.extra
var guavaVersion: String by rootProject.extra

dependencies {
    // spring boot
    api("org.springframework.boot:spring-boot-starter-web")

    // 数据库
    api("com.baomidou:mybatis-plus-boot-starter:${mybatisPlusVersion}")
    api("com.alibaba:druid-spring-boot-starter:${pagehelperVersion}")
    api("com.github.pagehelper:pagehelper-spring-boot-starter:${druidVersion}")

    // tool
    api("cn.hutool:hutool-all:${hutoolVersion}")
    api("org.apache.commons:commons-lang3")
    api("com.google.guava:guava:${guavaVersion}")

    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")
}

tasks.named<Jar>("jar") {
    enabled = true
}

模块

boot-shop-admin/build.gradle.kts 为空

api Gradle 脚本

plugins {
    id ("java-library")
    id("org.springframework.boot")
    id("io.spring.dependency-management")
}

dependencies {
    api(project(":boot-shop-common"))

    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")
}

tasks.named<Jar>("jar") {
    enabled = true
}

biz Gradle 脚本

plugins {
    id ("java-library")
    id("org.springframework.boot")
    id("io.spring.dependency-management")
}

dependencies {
    api(project(":boot-shop-admin:boot-shop-admin-api"))

    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")
}

tasks.named<Jar>("jar") {
    enabled = true
}

youtube 笔记

https://www.youtube.com/watch?v=Amx4Q6FKfHU&ab_channel=TechPaper

spring boot

顶层

Gradle Spring Boot_kotlin_13

子模块

Gradle Spring Boot_gradle_14

未解决

spring boot 为何对 gradle 的版本有强依赖

gradle 与 gradlew 的关系

gradle 版本与 gradlew 版本不一致时, gradle 脚本适配的是哪个版本的 gradle

kotlin dsl 与 groovy dsl 之间的区别本质在哪里

弃用所有子项目的 lombok 支持