马上 2025 年了,还在用 Maven 搭建 SpringBoot 项目吗?
点击关注公众号,“技术干货”及时达!
项目介绍这是我在今年9月研一开学后,选定了研究方向,就顺手用 Java 撸了一个「日语语言分析工具」。
除了它本来的功能,它在技术上的特点是如下三条:
在 springboot 中运行 java swing 界面(下图的界面就是用 swing 实现的)使用 gradle 搭建的父子项目,并支持 kotlin 混写内置一个 chromium 内核本文就着重介绍第二点。
主要技术:「java」 + 「kotlin」 + 「swing」 + 「springboot」 + 「gradle」
运行环境:「JetBrains Runtime with JCEF(Java 21)」
「在我看来,每一次项目开发都应该是一次技术的积累,经验的进步。」 所以在这次的项目搭建中,就尝试了「用 gradle 去代替以前 maven 父子项目的方案,同时拥抱下 kotlin」 。为什么会写这篇文章呢?因为在这次项目搭建过程中踩了很多坑。在这个项目中收获最大的就是掌握了基于 「gradle.kts」 的项目搭建。
除此之外,界面是 swing 做的,这也是我的一个强项,用 Java 手搓 GUI 。
「以下是主要界面:」
项目结构我不喜欢分享很难懂的东西。我尽力将本文内容写得简单,让大家都能看懂,也能够真正有所收获。
直接来看项目结构:
如图,项目结构其实很简单。虽然文件夹很多,但是真正只用关心的是中间的 gradle 子项目模块、 build.gradle.kts 、 settings.gradle.kts 这三个地方。
什么?你还不会创建 gradle 项目?其实很简单, Spring Initializr 会帮你创建。如图:
创建项目完成后,就可以将其改造为父子项目了。
父模块配置父模块配置依靠项目根目录下的 build.gradle.kts 、 settings.gradle.kts 。
先看 settings.gradle.kts :
rootProject.name = "cable-car"
include(":1-common")include(":1-reactivex")include(":1-spring-application")include(":2-jp-analysis-core")include(":3-client-framework")include(":4-web-jp-learning")可以很明显地看到,该配置文件中的 include(":xxxxx") 就是将上述项目结构中的各个模块引入到 settings.gradle.kts 中(记得不要忘记冒号)。 rootProject.name 即为项目名。
再来看 build.gradle.kts :
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
group = "com.hu.cablecar"version = "0.0.1"description = "缆车"
// Java 版本java { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21}
// 用于支持 Java 与 kotlin 混写,以及 lombok 依赖引入plugins { java kotlin("jvm") version "1.9.24" kotlin("plugin.lombok") version "1.9.24" id("io.freefair.lombok") version "8.10"}
// 全局配置allprojects {
// 将上述 plugins 应用到子模块 plugins.apply(JavaPlugin::class.java) plugins.apply("kotlin") plugins.apply("kotlin-lombok") plugins.apply("io.freefair.lombok")
// 仓库地址 repositories { maven { url = uri("https://maven.aliyun.com/nexus/content/groups/public/") } mavenCentral() mavenLocal() }
tasks.withTypeJavaCompile() { options.encoding = "UTF-8" }
tasks.withTypeJavadoc() { options.encoding = "UTF-8" }
tasks.withTypeKotlinCompile { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") jvmTarget = "21" } }}这就是 build.gradle.kts 需要准备的全部内容,可以很直观地看到,它主要就做了三件事:
定义了 Java 版本引入了 Java 、 kotlin 、 lombok 相关支持,并应用到子项目配置了依赖的 maven 下载地址子模块接下来就是子模块的介绍,怎么创建子模块,怎么将一个子模块引入到另一个子模块。
1-common:在上文项目结构中,我们先看最简单的子模块 1-common :
这个模块只包含三个 Java 写的工具类,以及一个 build.gradle.kts 配置文件。来看看配置文件的内容:
description = "公共基础模块"
dependencies { implementation("com.alibaba.fastjson2:fastjson2:2.0.45")}配置文件内容很简单:
description 描述了这个模块的名字仅在 dependencies 中引入了 fastjson2 依赖现在就能看到为什么要使用 gradle 来搭建项目了。因为相比于 maven , gradle 的配置文件真的很简单。
1-reactivex:看完最简单的子模块 1-common 后,来看看稍微复杂一点点的 1-reactivex 模块:
这个模块的作用是用 rxJava 实现了一个发布订阅的功能。这里的代码就是一直没时间单独写篇文章的那个“跨组件通信的 Java 版本”(没时间,真没时间...《下次一定》)。我只用RxJS,却搞定了三大框架的跨组件通信,甚至还能适用于Java(一、Angular篇)跨组件通信,远比你想象的要简 - 掘金
Java swing 的跨组件通信我就是用这个方法去做的(所以说功能的实现思路都是相通的。全栈的目的,就在于「不要将自己局限在一个语言甚至一个框架里面」)。
好了,题外话说完,来聊回这个模块的配置。来看 build.gradle.kts 配置文件:
description = "RX"
dependencies { // 像这样的写法,只会引入1-common自己的代码,不会引入它的依赖fastjson2 implementation(project(":1-common")) implementation("io.reactivex.rxjava3:rxjava:3.1.9")}从 dependencies 可以看到,这个模块不仅引入了 rxjava ,也引入了子模块 1-common ,因为该模块用到了它里面工具类的一个方法。
2-jp-analysis-core:同样的,这也是一个工具模块,用来做日语文字解析。代码结构与配置文件如下:
build.gradle.kts :
description = "日语分析核心模块"
plugins {}
dependencies { implementation(project(":1-common")) implementation("commons-io:commons-io:2.15.1")}可以看到,这个模块引入了 commons-io 和子模块 1-common 。
3-client-framework:重点来了,这是项目启动的 main 方法所在的模块,也是整个项目的界面。
它很复杂。引入了其它各个子模块,在使用 springboot 启动 swing 界面的同时,也使用了 Java 与 kotlin 混写。
来看看它的配置文件 build.gradle.kts :
description = "客户端UI框架"
plugins { // spring相关配置 kotlin("plugin.spring") version "1.9.24" id("org.springframework.boot") version "3.3.4" id("io.spring.dependency-management") version "1.1.6"}
dependencies { // 引入各个子模块 implementation(project(":1-common")) implementation(project(":1-reactivex")) implementation(project(":1-spring-application")) implementation(project(":2-jp-analysis-core")) implementation(project(":4-web-jp-learning")) // 引入maven依赖 // 在上面引入子模块时,不会引入子模块自己的依赖 // 所以如果在此使用了同样的依赖例如这里的commons-io与rxjava,需要在该模块中再次引入 implementation("org.springframework.boot:spring-boot-starter") implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-tomcat") implementation("io.reactivex.rxjava3:rxjava") implementation("commons-io:commons-io:2.15.1") // 引入本地jar依赖 implementation(files("lib/ui/flatlaf-3.5.2.jar")) implementation(files("lib/ui/flatlaf-intellij-themes-3.5.2.jar")) implementation(files("lib/ui/JTattoo-1.6.13.jar"))}
tasks.jar { // 设置gradle任务:打包为jar enabled = true manifest { attributes(mapOf("Main-Class" to "com.hu.cablecar.client.framework.ClientFrameworkApplication")) }}可以在配置文件中看到:
plugins 做了 spring 相关配置,以及 spring 的 kotlin 配置dependencies 中引入各个子模块以及相关依赖tasks.jar 配置了 gradle 的打包为 jar 的任务配置了 task.jar 后,可以在此执行相应的任务,将该模块打包为 jar 。
于是能够看出,即使是复杂的模块,其 gradle 配置依然简单清爽。如果是 maven 的 pom.xml 配置,那么肯定就不只这么一点代码了。
由于在根目录下的 build.gradle.kts 中配置了 kotlin ,以及在该模块也进行了 spring 的 kotlin 配置,在该模块中,是可以直接写 kotlin 代码的,并能和 java 代码互相引用。
该图是之前写过的这个文章的内容的代码,在此将其改为 kotlin 了:一种解决Swing中JLabel图片在高分屏上显示不正常的方案Java Swing 在高分屏上图片显示模糊,即 JLab - 掘金
该图是用 kotlin 去写了一个 spring 配置类。
开头有讲到其内置了一个 chromium 内核,用处就是我在里面放了我的个人网站:
日语笔记 - intelyes.club
总结再回顾下项目结构:
我们只用关心根目录下的配置文件以及每个子项目下的配置文件:
1-common1-reactivex1-spring-application2-jp-analysis-core3-client-framework4-web-jp-learning在 gradle 父子项目中,只用关心根目录下的 build.gradle.kts 、 settings.gradle.kts ,以及各个子模块的 build.gradle.kts 。这一点和 maven 父子项目相似。
但是配置文件的内容很比 maven 的 pom.xml 简单:
根目录下的 settings.gradle.kts 中声明每个子模块根目录下的 build.gradle.kts 中进行 java 、 kotlin 相关配置等各个子模块下的 build.gradle.kts 中声明该模块的依赖引用等这个项目由于还没提交到 git ,本地依赖与 native 非常多,代码就暂时不分享了。等到以后整理完成并完善后,会考虑单独写一篇文详细介绍其功能。
如有不懂的欢迎留言讨论!
点击关注公众号,“技术干货”及时达!
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线