diff --git a/build.gradle.kts b/build.gradle.kts index b9bdcf3..42fe203 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,7 +36,6 @@ allprojects { ext { set(ProjectFlags.IS_ROOT_MODULE, false) set(ProjectFlags.USE_SPRING_BOOT_BOM, false) - set(ProjectFlags.USE_SPRING_BOOT_WEB, false) } afterEvaluate { if (project.getPropertyByBoolean(ProjectFlags.IS_ROOT_MODULE)) { @@ -58,11 +57,6 @@ subprojects { implementation(platform(libs.springBootDependencies.bom)) } } - if (project.getPropertyByBoolean(ProjectFlags.USE_SPRING_BOOT_WEB)) { - dependencies { - compileOnly(libs.springBootStarter.web) - } - } } val libs = rootProject.libs apply { @@ -70,7 +64,6 @@ subprojects { plugin(libs.plugins.maven.publish.get().pluginId) plugin(libs.plugins.kotlin.jvm.get().pluginId) plugin(libs.plugins.axionRelease.get().pluginId) -// plugin(libs.plugins.spring.dependency.management.get().pluginId) //导入仓库配置 from(file("$configDir/repositories.gradle.kts")) // 导入源代码任务 @@ -91,6 +84,22 @@ subprojects { password = System.getenv("GITHUB_TOKEN") } } + val host = System.getenv("GEWUYOU_GITEA_HOST") + host?.let { + maven { + isAllowInsecureProtocol = true + name = "Gitea" + url = uri("http://${it}/api/packages/gewuyou/maven") + credentials(HttpHeaderCredentials::class.java) { + name = "Authorization" + value = "token ${System.getenv("GEWUYOU_GITEA_TOKEN")}" + } + authentication { + create("header", HttpHeaderAuthentication::class.java) + } + } + } + } publications { create("mavenJava") { diff --git a/buildSrc/src/main/kotlin/ProjectFlags.kt b/buildSrc/src/main/kotlin/ProjectFlags.kt index 8cdba14..7c663bd 100644 --- a/buildSrc/src/main/kotlin/ProjectFlags.kt +++ b/buildSrc/src/main/kotlin/ProjectFlags.kt @@ -1,5 +1,4 @@ object ProjectFlags { const val IS_ROOT_MODULE = "isRootModule" const val USE_SPRING_BOOT_BOM = "useSpringBootBom" - const val USE_SPRING_BOOT_WEB = "useSpringBootWeb" } \ No newline at end of file diff --git a/forgeboot-webmvc/forgeboot-webmvc-logger-starter/.gitattributes b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/.gitattributes new file mode 100644 index 0000000..8af972c --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/forgeboot-webmvc/forgeboot-webmvc-logger-starter/.gitignore b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/.gitignore new file mode 100644 index 0000000..5a979af --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/.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-webmvc/forgeboot-webmvc-logger-starter/build.gradle.kts b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/build.gradle.kts new file mode 100644 index 0000000..230d590 --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/build.gradle.kts @@ -0,0 +1,12 @@ +extra { + // 需要SpringBootBom + setProperty(ProjectFlags.USE_SPRING_BOOT_BOM, true) +} +dependencies { + implementation(project(Modules.Core.EXTENSION)) + implementation(libs.springBootStarter.aop) + + implementation(libs.kotlinxCoroutines.reactor) + + compileOnly(libs.springBootStarter.web) +} diff --git a/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/annotation/MethodRecording.kt b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/annotation/MethodRecording.kt new file mode 100644 index 0000000..a4635e1 --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/annotation/MethodRecording.kt @@ -0,0 +1,14 @@ +package com.gewuyou.forgeboot.webmvc.logger.annotation + +/** + * 记录方法的注解: 记录出参入参,方法执行耗时等信息 + * + * @since 2025-01-23 14:22:11 + * @author gewuyou + */ +// 注解用于函数 +@Target(AnnotationTarget.FUNCTION) +// 在运行时可用 +@Retention(AnnotationRetention.RUNTIME) +@MustBeDocumented +annotation class MethodRecording(val description: String = "",val printArgs: Boolean = true,val printResult: Boolean = true,val printTime: Boolean = true) \ No newline at end of file diff --git a/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/aspect/MethodRecordingAspect.kt b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/aspect/MethodRecordingAspect.kt new file mode 100644 index 0000000..f84b3dd --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/aspect/MethodRecordingAspect.kt @@ -0,0 +1,86 @@ +package com.gewuyou.forgeboot.webmvc.logger.aspect + + +import com.gewuyou.forgeboot.core.extension.log +import com.gewuyou.forgeboot.webmvc.logger.annotation.MethodRecording +import com.gewuyou.forgeboot.webmvc.logger.entities.CoroutineLogger +import org.aspectj.lang.ProceedingJoinPoint +import org.aspectj.lang.annotation.Around +import org.aspectj.lang.annotation.Aspect +/** + * 方法记录切面 + * + * 该切面用于拦截带有@MethodRecording注解的方法,记录方法的执行信息,包括方法开始执行、执行完成、执行失败等信息 + * 可以通过@MethodRecording注解的属性选择性打印方法的入参、返回值和执行耗时等信息 + * + * @since 2025-01-23 14:25:04 + * @author gewuyou + */ +@Aspect +class MethodRecordingAspect { + + /** + * 环绕通知,用于在方法执行前后进行操作 + * + * @param joinPoint 切入点,包含被拦截方法的信息 + * @param methodRecording 方法记录注解,包含配置信息 + * @return 方法的执行结果 + * @throws Throwable 方法执行过程中抛出的异常 + */ + @Around("@annotation(methodRecording)") + fun methodRecording(joinPoint: ProceedingJoinPoint, methodRecording: MethodRecording): Any? { + // 获取方法名 + val methodName = joinPoint.signature.name + // 获取类名 + val className = joinPoint.signature.declaringTypeName + // 获取注解的描述信息 + val description = methodRecording.description + // 获取方法的入参 + val args = joinPoint.args + + // 安全地记录日志,防止日志记录失败 + CoroutineLogger.safeLog { + // 构建日志字符串,包括方法开始执行的信息、注解的描述信息和入参信息 + val logStr = buildString { + append("开始执行方法: $className.$methodName\n") + append("$description\n") + if (methodRecording.printArgs) { + append("入参: ${args.joinToString()}\n") + } + } + log.info(logStr) + } + + // 记录方法开始执行的时间 + val startTime = System.currentTimeMillis() + + // 尝试执行方法 + return try { + val result = joinPoint.proceed() + val endTime = System.currentTimeMillis() + val duration = endTime - startTime + + // 安全地记录日志,记录方法执行完成的信息、返回值信息和执行耗时信息 + CoroutineLogger.safeLog { + val logStr = buildString { + append("方法 $className.$methodName 执行完成\n") + if (methodRecording.printResult) { + append("返回值: $result\n") + } + if (methodRecording.printTime) { + append("执行耗时: ${duration}ms") + } + } + log.info(logStr) + } + + result + } catch (ex: Throwable) { + // 如果方法执行失败,安全地记录错误日志 + CoroutineLogger.safeLog { + log.error("方法 $className.$methodName 执行失败: ${ex.message}", ex) + } + throw ex + } + } +} diff --git a/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/config/LoggerAutoConfiguration.kt b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/config/LoggerAutoConfiguration.kt new file mode 100644 index 0000000..d77d68f --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/config/LoggerAutoConfiguration.kt @@ -0,0 +1,32 @@ +package com.gewuyou.forgeboot.webmvc.logger.config + +import com.gewuyou.forgeboot.core.extension.log +import com.gewuyou.forgeboot.webmvc.logger.aspect.MethodRecordingAspect +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +/** + * Logger自动配置 + * + * 该类用于自动配置Logger,通过Spring的自动配置机制,自动加载和配置Logger + * 它定义了一个Bean方法,用于创建和配置MethodRecordingAspect切面对象 + * + * @since 2025-04-26 21:02:56 + * @author gewuyou + */ +@Configuration +open class LoggerAutoConfiguration { + /** + * 创建并返回一个MethodRecordingAspect切面对象 + * + * 该方法定义了一个Bean,用于在Spring容器中创建并配置一个MethodRecordingAspect切面对象 + * MethodRecordingAspect切面对象用于记录方法的执行日志,以便于监控和调试 + * + * @return MethodRecordingAspect切面对象 + */ + @Bean + open fun methodRecordingAspect(): MethodRecordingAspect { + log.info("创建方法记录切面!") + return MethodRecordingAspect() + } +} diff --git a/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/entities/CoroutineLogger.kt b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/entities/CoroutineLogger.kt new file mode 100644 index 0000000..62f763c --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/kotlin/com/gewuyou/forgeboot/webmvc/logger/entities/CoroutineLogger.kt @@ -0,0 +1,34 @@ +package com.gewuyou.forgeboot.webmvc.logger.entities + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch + +/** + * 协程日志对象,用于在协程环境中安全地记录日志 + * + * @since 2025-04-26 19:20:43 + * @author gewuyou + */ +object CoroutineLogger { + // 创建一个协程作用域,使用SupervisorJob和IO调度器,适合进行IO密集型的日志记录任务 + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + + /** + * 安全地执行日志记录block,异常会被捕获并忽略,确保日志记录的稳定性 + * + * @param block 日志记录的协程block,包含实际的日志记录逻辑 + */ + fun safeLog(block: suspend () -> Unit) { + // 在协程作用域中启动一个新的协程来执行日志记录任务 + scope.launch { + try { + // 尝试执行日志记录block + block() + } catch (ex: Exception) { + // 吞噬日志错误,确保协程稳定运行,不会因单个日志记录失败而崩溃 + } + } + } +} diff --git a/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..31e47c9 --- /dev/null +++ b/forgeboot-webmvc/forgeboot-webmvc-logger-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.gewuyou.forgeboot.webmvc.logger.config.LoggerAutoConfiguration \ No newline at end of file diff --git a/forgeboot-webmvc/forgeboot-webmvc-version-starter/build.gradle.kts b/forgeboot-webmvc/forgeboot-webmvc-version-starter/build.gradle.kts index 3864ecf..584f7c6 100644 --- a/forgeboot-webmvc/forgeboot-webmvc-version-starter/build.gradle.kts +++ b/forgeboot-webmvc/forgeboot-webmvc-version-starter/build.gradle.kts @@ -1,8 +1,9 @@ extra { - // 标记为根项目 + // 需要SpringBootBom setProperty(ProjectFlags.USE_SPRING_BOOT_BOM, true) - setProperty(ProjectFlags.USE_SPRING_BOOT_WEB, true) } dependencies { implementation(project(Modules.Core.EXTENSION)) + + compileOnly(libs.springBootStarter.web) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 419c8f9..91fabd9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ kotlin-version = "2.0.0" kotlinxDatetime-version = "0.6.1" kotlinxSerializationJSON-version = "1.7.3" -kotlinxCoroutines-version = "1.9.0" +#kotlinxCoroutines-version = "1.9.0" axion-release-version = "1.18.7" spring-boot-version = "3.4.4" @@ -15,16 +15,20 @@ slf4j-version = "2.0.17" kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin-version" } kotlinxDatetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime-version" } kotlinxSerialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJSON-version" } -kotlinxCoroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines-version" } - +#kotlinxCoroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines-version" } +kotlinxCoroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" } +# kotlinx +# 响应式协程库 +kotlinxCoroutines-reactor = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-reactor" } slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j-version" } +springBootStarter-aop = { group = "org.springframework.boot", name = "spring-boot-starter-aop" } springBootStarter-web = { group = "org.springframework.boot", name = "spring-boot-starter-web" } springBootDependencies-bom = { module = "org.springframework.boot:spring-boot-dependencies", version.ref = "spring-boot-version" } # Libraries can be bundled together for easier import [bundles] -kotlinxEcosystem = ["kotlinxDatetime", "kotlinxSerialization", "kotlinxCoroutines"] +kotlinxEcosystem = ["kotlinxDatetime", "kotlinxSerialization", "kotlinxCoroutines-core"] [plugins] # 应用 Java 插件,提供基本的 Java 代码编译和构建能力