From bd0355844014aa4b0466d78da2c871f8054f19a8 Mon Sep 17 00:00:00 2001 From: gewuyou Date: Tue, 3 Jun 2025 15:09:03 +0800 Subject: [PATCH] feat(banner): Add Forge Banner Module - Added Banner module, including API, implementation and automatic configuration components - Add banner configuration properties and policy enumeration - Implement configurable banner provider class - Create necessary project structures and configuration files --- buildSrc/src/main/kotlin/Modules.kt | 6 ++ forgeboot-banner/.gitattributes | 3 + forgeboot-banner/.gitignore | 40 ++++++++++ forgeboot-banner/build.gradle.kts | 6 ++ .../forgeboot-banner-api/.gitattributes | 3 + .../forgeboot-banner-api/.gitignore | 40 ++++++++++ .../forgeboot-banner-api/build.gradle.kts | 6 ++ .../api/config/entities/BannerProperties.kt | 16 ++++ .../banner/api/enums/BannerStrategy.kt | 13 ++++ .../banner/api/provider/BannerProvider.kt | 18 +++++ .../forgeboot-banner-impl/.gitattributes | 3 + .../forgeboot-banner-impl/.gitignore | 40 ++++++++++ .../forgeboot-banner-impl/build.gradle.kts | 6 ++ .../banner/impl/ConfigurableBannerProvider.kt | 75 +++++++++++++++++++ .../src/main/resources/application.properties | 1 + .../forgeboot-banner-launcher/.gitattributes | 3 + .../forgeboot-banner-launcher/.gitignore | 40 ++++++++++ .../build.gradle.kts | 8 ++ .../launcher/SpringApplicationExtensions.kt | 34 +++++++++ 19 files changed, 361 insertions(+) create mode 100644 forgeboot-banner/.gitattributes create mode 100644 forgeboot-banner/.gitignore create mode 100644 forgeboot-banner/build.gradle.kts create mode 100644 forgeboot-banner/forgeboot-banner-api/.gitattributes create mode 100644 forgeboot-banner/forgeboot-banner-api/.gitignore create mode 100644 forgeboot-banner/forgeboot-banner-api/build.gradle.kts create mode 100644 forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/config/entities/BannerProperties.kt create mode 100644 forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/enums/BannerStrategy.kt create mode 100644 forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/provider/BannerProvider.kt create mode 100644 forgeboot-banner/forgeboot-banner-impl/.gitattributes create mode 100644 forgeboot-banner/forgeboot-banner-impl/.gitignore create mode 100644 forgeboot-banner/forgeboot-banner-impl/build.gradle.kts create mode 100644 forgeboot-banner/forgeboot-banner-impl/src/main/kotlin/com/gewuyou/forgeboot/banner/impl/ConfigurableBannerProvider.kt create mode 100644 forgeboot-banner/forgeboot-banner-impl/src/main/resources/application.properties create mode 100644 forgeboot-banner/forgeboot-banner-launcher/.gitattributes create mode 100644 forgeboot-banner/forgeboot-banner-launcher/.gitignore create mode 100644 forgeboot-banner/forgeboot-banner-launcher/build.gradle.kts create mode 100644 forgeboot-banner/forgeboot-banner-launcher/src/main/kotlin/com/gewuyou/forgeboot/banner/launcher/SpringApplicationExtensions.kt diff --git a/buildSrc/src/main/kotlin/Modules.kt b/buildSrc/src/main/kotlin/Modules.kt index b9ef2d9..9548840 100644 --- a/buildSrc/src/main/kotlin/Modules.kt +++ b/buildSrc/src/main/kotlin/Modules.kt @@ -30,4 +30,10 @@ object Modules { const val IMPL = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-impl" const val AUTOCONFIGURE = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-autoconfigure" } + object Banner { + const val STARTER = ":forgeboot-banner" + const val API = ":forgeboot-banner:forgeboot-banner-api" + const val IMPL = ":forgeboot-banner:forgeboot-banner-impl" + const val AUTOCONFIGURE = ":forgeboot-banner:forgeboot-banner-autoconfigure" + } } \ No newline at end of file diff --git a/forgeboot-banner/.gitattributes b/forgeboot-banner/.gitattributes new file mode 100644 index 0000000..8af972c --- /dev/null +++ b/forgeboot-banner/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/forgeboot-banner/.gitignore b/forgeboot-banner/.gitignore new file mode 100644 index 0000000..5a979af --- /dev/null +++ b/forgeboot-banner/.gitignore @@ -0,0 +1,40 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Kotlin ### +.kotlin diff --git a/forgeboot-banner/build.gradle.kts b/forgeboot-banner/build.gradle.kts new file mode 100644 index 0000000..614c016 --- /dev/null +++ b/forgeboot-banner/build.gradle.kts @@ -0,0 +1,6 @@ +extra{ + setProperty(ProjectFlags.IS_ROOT_MODULE,true) +} +dependencies { + +} diff --git a/forgeboot-banner/forgeboot-banner-api/.gitattributes b/forgeboot-banner/forgeboot-banner-api/.gitattributes new file mode 100644 index 0000000..8af972c --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-api/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/forgeboot-banner/forgeboot-banner-api/.gitignore b/forgeboot-banner/forgeboot-banner-api/.gitignore new file mode 100644 index 0000000..5a979af --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-api/.gitignore @@ -0,0 +1,40 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Kotlin ### +.kotlin diff --git a/forgeboot-banner/forgeboot-banner-api/build.gradle.kts b/forgeboot-banner/forgeboot-banner-api/build.gradle.kts new file mode 100644 index 0000000..71f7f92 --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-api/build.gradle.kts @@ -0,0 +1,6 @@ + +dependencies { + compileOnly(platform(libs.springBootDependencies.bom)) + compileOnly(libs.springBootStarter.web) + kapt(libs.springBoot.configuration.processor) +} diff --git a/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/config/entities/BannerProperties.kt b/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/config/entities/BannerProperties.kt new file mode 100644 index 0000000..081fa63 --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/config/entities/BannerProperties.kt @@ -0,0 +1,16 @@ +package com.gewuyou.forgeboot.banner.api.config.entities + +import com.gewuyou.forgeboot.banner.api.enums.BannerStrategy +import org.springframework.boot.context.properties.ConfigurationProperties + +/** + *横幅配置 + * + * @since 2025-06-03 12:55:18 + * @author gewuyou + */ +@ConfigurationProperties("forgeboot.banner") +class BannerProperties { + var path: String = "banners/" + var strategy: BannerStrategy = BannerStrategy.Random +} \ No newline at end of file diff --git a/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/enums/BannerStrategy.kt b/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/enums/BannerStrategy.kt new file mode 100644 index 0000000..f7725c1 --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/enums/BannerStrategy.kt @@ -0,0 +1,13 @@ +package com.gewuyou.forgeboot.banner.api.enums + +/** + *横幅策略 + * + * @since 2025-06-03 13:04:30 + * @author gewuyou + */ +enum class BannerStrategy { + First, + Random, + All +} \ No newline at end of file diff --git a/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/provider/BannerProvider.kt b/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/provider/BannerProvider.kt new file mode 100644 index 0000000..79de9fd --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-api/src/main/kotlin/com/gewuyou/forgeboot/banner/api/provider/BannerProvider.kt @@ -0,0 +1,18 @@ +package com.gewuyou.forgeboot.banner.api.provider + +import java.io.PrintStream + +/** + * 横幅提供商接口,用于定义横幅输出行为 + * + * @since 2025-06-03 12:17:19 + * @author gewuyou + */ +fun interface BannerProvider { + /** + * 输出横幅内容到指定的输出流 + * + * @param out 输出流对象 + */ + fun printBanner(out: PrintStream) +} \ No newline at end of file diff --git a/forgeboot-banner/forgeboot-banner-impl/.gitattributes b/forgeboot-banner/forgeboot-banner-impl/.gitattributes new file mode 100644 index 0000000..8af972c --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-impl/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/forgeboot-banner/forgeboot-banner-impl/.gitignore b/forgeboot-banner/forgeboot-banner-impl/.gitignore new file mode 100644 index 0000000..5a979af --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-impl/.gitignore @@ -0,0 +1,40 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Kotlin ### +.kotlin diff --git a/forgeboot-banner/forgeboot-banner-impl/build.gradle.kts b/forgeboot-banner/forgeboot-banner-impl/build.gradle.kts new file mode 100644 index 0000000..b269c06 --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-impl/build.gradle.kts @@ -0,0 +1,6 @@ + +dependencies { + compileOnly(platform(libs.springBootDependencies.bom)) + compileOnly(libs.springBootStarter.web) + compileOnly(project(Modules.Banner.API)) +} diff --git a/forgeboot-banner/forgeboot-banner-impl/src/main/kotlin/com/gewuyou/forgeboot/banner/impl/ConfigurableBannerProvider.kt b/forgeboot-banner/forgeboot-banner-impl/src/main/kotlin/com/gewuyou/forgeboot/banner/impl/ConfigurableBannerProvider.kt new file mode 100644 index 0000000..7349097 --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-impl/src/main/kotlin/com/gewuyou/forgeboot/banner/impl/ConfigurableBannerProvider.kt @@ -0,0 +1,75 @@ +package com.gewuyou.forgeboot.banner.impl + +import com.gewuyou.forgeboot.banner.api.enums.BannerStrategy +import com.gewuyou.forgeboot.banner.api.provider.BannerProvider +import com.gewuyou.forgeboot.banner.api.config.entities.BannerProperties +import org.springframework.core.io.Resource +import org.springframework.core.io.support.PathMatchingResourcePatternResolver +import java.io.PrintStream +import java.util.Random +import java.util.Scanner + + +/** + * 可配置横幅提供者类,根据配置属性输出横幅 + * + * @param properties 横幅属性配置对象 + */ +class ConfigurableBannerProvider( + private val properties: BannerProperties, +): BannerProvider { + /** + * 输出横幅内容到指定的输出流 + * + * @param out 输出流对象,可为空 + */ + override fun printBanner(out: PrintStream) { + try { + // 根据属性配置获取横幅资源路径模式 + val pattern = "classpath*:" + properties.path + "*.txt" + // 使用路径匹配获取所有符合条件的资源 + val resources: Array = PathMatchingResourcePatternResolver().getResources(pattern) + // 如果没有找到任何资源,则输出提示信息并返回 + if (resources.isEmpty()) { + out.println("No banner found in: " + properties.path) + return + } + // 根据配置的策略选择横幅输出方式 + when (properties.strategy) { + BannerStrategy.First-> resources[0]?.let { printResource(it, out) } + BannerStrategy.Random -> resources[Random().nextInt(resources.size)]?.let { printResource(it, out) } + BannerStrategy.All -> { + for (resource in resources) { + resource?.let { printResource(it, out) } + out.println() + } + } + } + } catch (e: Exception) { + // 异常处理:输出错误信息 + out.println("Error loading banners: " + e.message) + } + } + + /** + * 打印资源内容到指定的输出流 + * + * @param resource 要打印的资源对象 + * @param out 输出流对象 + */ + private fun printResource(resource: Resource, out: PrintStream) { + try { + // 使用输入流读取资源内容并输出 + resource.inputStream.use { `is` -> + Scanner(`is`).useDelimiter("\\A").use { scanner -> + while (scanner.hasNext()) { + out.println(scanner.next()) + } + } + } + } catch (e: java.lang.Exception) { + // 异常处理:输出错误信息 + out.println("Failed to print banner: " + e.message) + } + } +} diff --git a/forgeboot-banner/forgeboot-banner-impl/src/main/resources/application.properties b/forgeboot-banner/forgeboot-banner-impl/src/main/resources/application.properties new file mode 100644 index 0000000..e72a424 --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-impl/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.application.name=forgeboot-banner-impl diff --git a/forgeboot-banner/forgeboot-banner-launcher/.gitattributes b/forgeboot-banner/forgeboot-banner-launcher/.gitattributes new file mode 100644 index 0000000..8af972c --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-launcher/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/forgeboot-banner/forgeboot-banner-launcher/.gitignore b/forgeboot-banner/forgeboot-banner-launcher/.gitignore new file mode 100644 index 0000000..5a979af --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-launcher/.gitignore @@ -0,0 +1,40 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Kotlin ### +.kotlin diff --git a/forgeboot-banner/forgeboot-banner-launcher/build.gradle.kts b/forgeboot-banner/forgeboot-banner-launcher/build.gradle.kts new file mode 100644 index 0000000..67b06ee --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-launcher/build.gradle.kts @@ -0,0 +1,8 @@ + +dependencies { + compileOnly(platform(libs.springBootDependencies.bom)) + compileOnly(libs.springBootStarter.web) + compileOnly(project(Modules.Banner.IMPL)) + compileOnly(project(Modules.Banner.API)) + implementation(project(Modules.Core.EXTENSION)) +} diff --git a/forgeboot-banner/forgeboot-banner-launcher/src/main/kotlin/com/gewuyou/forgeboot/banner/launcher/SpringApplicationExtensions.kt b/forgeboot-banner/forgeboot-banner-launcher/src/main/kotlin/com/gewuyou/forgeboot/banner/launcher/SpringApplicationExtensions.kt new file mode 100644 index 0000000..7fa3a83 --- /dev/null +++ b/forgeboot-banner/forgeboot-banner-launcher/src/main/kotlin/com/gewuyou/forgeboot/banner/launcher/SpringApplicationExtensions.kt @@ -0,0 +1,34 @@ +package com.gewuyou.forgeboot.banner.launcher + +import com.gewuyou.forgeboot.banner.api.config.entities.BannerProperties +import com.gewuyou.forgeboot.banner.impl.ConfigurableBannerProvider +import org.springframework.boot.Banner +import org.springframework.boot.builder.SpringApplicationBuilder +import org.springframework.boot.context.properties.bind.Binder +import org.springframework.core.env.StandardEnvironment + + +/** + * 使用Forge横幅运行Spring应用的函数 + * 该函数主要用于简化Spring应用的启动过程,特别是当需要自定义横幅时 + * 它通过反射启动一个Spring应用,并允许开发者在启动时自定义横幅 + * + * @param T Spring应用的主类类型,必须是Any的子类 + * @param args 命令行参数,传递给Spring应用 + */ +inline fun runApplicationWithForgeBanner(vararg args: String) { + // 创建并配置Spring应用的环境 + val env = StandardEnvironment() + // 获取配置属性绑定器 + val binder = Binder.get(env) + // 从配置中绑定BannerProperties属性,如果没有找到,则使用默认值 + val props = binder.bind("banner", BannerProperties::class.java).orElse(BannerProperties()) + // 创建一个自定义的Banner实例 + val banner = Banner { _, _, out -> ConfigurableBannerProvider(props).printBanner(out) } + // 构建并运行Spring应用 + SpringApplicationBuilder() + .sources(T::class.java) + .banner(banner) + .environment(env) + .run(*args) +}