feat(module): Added forgeboot-common module

- Add forgeboot-common result processing related submodules - Implement unified response encapsulation class R and related interfaces
- Integrated international message parsing and request ID generation function
- Update project configuration to support the construction and release of new modules
This commit is contained in:
gewuyou 2025-05-03 17:33:17 +08:00
parent 1537973803
commit 3ce3cedc0f
32 changed files with 663 additions and 23 deletions

View File

@ -1,6 +1,7 @@
plugins {
// 基本 Java 支持
alias(libs.plugins.java)
alias(libs.plugins.javaLibrary)
// Maven 发布支持
alias(libs.plugins.maven.publish)
// 语义版本插件
@ -8,6 +9,8 @@ plugins {
// Kotlin Spring 支持
alias(libs.plugins.kotlin.plugin.spring)
}
// 配置 SCM 版本插件
scmVersion {
tag {
prefix.set("") // 不加 v生成 1.0.1 而不是 v1.0.1
@ -24,13 +27,16 @@ scmVersion {
pre("commit")
post("push")
}
}
// 设置项目版本
version = scmVersion.version
// 配置目录路径
val configDir = "$rootDir/config/"
val tasksDir = "$configDir/tasks/"
// 全局项目配置
allprojects {
// 设置全局属性
ext {
@ -48,21 +54,18 @@ allprojects {
}
project.group = "com.gewuyou.forgeboot"
}
// 子项目配置
subprojects {
version = rootProject.version
afterEvaluate {
val isRootModule = project.getPropertyByBoolean(ProjectFlags.IS_ROOT_MODULE)
val isStarterModule = project.name.contains("starter")
if (isRootModule) {
dependencies {
project.subprojects.forEach {
if (!it.getPropertyByBoolean(ProjectFlags.IS_ROOT_MODULE)) {
project.dependencies.add("api", project(it.path))
}
}
}
}
val parentProject = project.parent
// 让父项目引入子项目
parentProject?.dependencies?.add("api", project(project.path))
if (isStarterModule && !isRootModule) {
// Starter 模块依赖配置
dependencies {
implementation(platform(libs.springBootDependencies.bom))
implementation(platform(libs.springCloudDependencies.bom))
@ -70,9 +73,11 @@ subprojects {
}
}
}
// 应用插件和配置
val libs = rootProject.libs
apply {
plugin(libs.plugins.java.get().pluginId)
plugin(libs.plugins.javaLibrary.get().pluginId)
plugin(libs.plugins.maven.publish.get().pluginId)
plugin(libs.plugins.kotlin.jvm.get().pluginId)
plugin(libs.plugins.axionRelease.get().pluginId)
@ -81,13 +86,16 @@ subprojects {
// 导入源代码任务
from(file("$tasksDir/sourceTask.gradle.kts"))
}
//region publishing
// 发布配置
publishing {
repositories {
// 本地仓库
maven {
name = "localRepo"
url = uri("file://D:/Maven/mvn_repository")
}
// GitHub Packages 仓库
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/GeWuYou/forgeboot")
@ -96,6 +104,7 @@ subprojects {
password = System.getenv("GITHUB_TOKEN")
}
}
// Gitea 仓库
val host = System.getenv("GEWUYOU_GITEA_HOST")
host?.let {
maven {
@ -111,7 +120,6 @@ subprojects {
}
}
}
}
publications {
create<MavenPublication>("mavenJava") {
@ -148,15 +156,20 @@ subprojects {
}
}
}
//endregion
// 依赖配置
dependencies {
}
// Java 插件扩展配置
configure<JavaPluginExtension> {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
// 任务配置
tasks.withType<Jar> {
isEnabled = true
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
@ -165,6 +178,8 @@ subprojects {
useJUnitPlatform()
}
}
// 获取项目布尔属性的辅助函数
fun Project.getPropertyByBoolean(key: String): Boolean {
return properties[key]?.toString()?.toBoolean() ?: false
}

View File

@ -16,4 +16,10 @@ object Modules {
const val ROOT = ":forgeboot-core"
const val EXTENSION = ":forgeboot-core:forgeboot-core-extension"
}
object Common {
const val ROOT = ":forgeboot-common"
const val RESULT = ":forgeboot-common:forgeboot-common-result"
const val RESULT_IMPL = ":forgeboot-common:forgeboot-common-result:forgeboot-common-result-impl"
const val RESULT_API = ":forgeboot-common:forgeboot-common-result:forgeboot-common-result-api"
}
}

View File

@ -1,5 +1,3 @@
object ProjectFlags {
const val IS_ROOT_MODULE = "isRootModule"
const val USE_SPRING_BOOT_BOM = "useSpringBootBom"
const val USE_CONFIGURATION_PROCESSOR = "useConfigurationProcessor"
}

3
forgeboot-common/.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

40
forgeboot-common/.gitignore vendored Normal file
View File

@ -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

View File

@ -0,0 +1,7 @@
extra {
// 标记为根项目
setProperty(ProjectFlags.IS_ROOT_MODULE, true)
}
dependencies {
}

View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -0,0 +1,7 @@
extra {
// 标记为根项目
setProperty(ProjectFlags.IS_ROOT_MODULE, true)
}
dependencies {
}

View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -0,0 +1,37 @@
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/

View File

@ -0,0 +1,4 @@
dependencies {
}

View File

@ -0,0 +1,23 @@
package com.gewuyou.forgeboot.common.result.api
/**
* 消息解析器接口
*
* 用于根据消息代码和参数解析出具体的消息文本
* 这个接口的主要作用是定义一个标准的消息解析方法以便在不同的上下文中解析消息
*
* @since 2025-05-03 16:10:26
* @author gewuyou
*/
fun interface MessageResolver {
/**
* 解析消息
*
* 根据给定的消息代码和可选的参数数组解析并返回具体的消息字符串
* 这个方法允许在不同的上下文中重用消息解析逻辑并可以根据需要提供不同的实现
*
* @param code 消息代码用于标识特定的消息类型或模板
* @param args 可选的消息参数数组用于替换消息模板中的占位符
* @return 解析后的消息字符串
*/
fun resolve(code: String, args: Array<Any>?): String
}

View File

@ -0,0 +1,20 @@
package com.gewuyou.forgeboot.common.result.api
/**
* 请求ID提供商接口
*
* 该接口用于获取请求ID请求ID是用于跟踪和调试的唯一标识符
* 它可以帮助开发者在日志和监控系统中追踪请求的来源和流向
*
* @since 2025-05-03 16:12:44
* @author gewuyou
*/
fun interface RequestIdProvider {
/**
* 获取请求ID
*
* 返回一个唯一的字符串标识符作为请求ID
*
* @return 请求ID的字符串表示
*/
fun getRequestId(): String
}

View File

@ -0,0 +1,27 @@
package com.gewuyou.forgeboot.common.result.api
/**
* 响应信息
*
* @author gewuyou
* @since 2025-05-03 16:31:59
*/
interface ResponseInformation {
/**
* 获取响应码
* @return 响应码
*/
val responseCode: Int
/**
* 获取i18n响应信息code
* @return 响应信息 code
*/
val responseI8nMessageCode: String
/**
* 获取i18n响应信息参数
* @return 响应信息参数
*/
val responseI8nMessageArgs: Array<Any>?
}

View File

@ -0,0 +1,21 @@
package com.gewuyou.forgeboot.common.result.api
/**
* 结果扩展器
*
* 用于扩展结果映射通过实现此接口可以自定义逻辑以向结果映射中添加修改或删除元素
* 主要用于在某个处理流程结束后对结果数据进行额外的处理或装饰
*
* @since 2025-05-03 16:08:55
* @author gewuyou
*/
fun interface ResultExtender {
/**
* 扩展结果映射
*
* 实现此方法以执行扩展逻辑可以访问并修改传入的结果映射
* 例如可以用于添加额外的信息修改现有值或者根据某些条件删除条目
*
* @param resultMap 一个包含结果数据的可变映射可以在此方法中对其进行修改
*/
fun extend(resultMap: MutableMap<String, Any?>)
}

View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View File

@ -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

View File

@ -0,0 +1,5 @@
dependencies {
implementation(project(Modules.Common.RESULT_API))
}

View File

@ -0,0 +1,187 @@
package com.gewuyou.forgeboot.common.result
import com.gewuyou.forgeboot.common.result.api.MessageResolver
import com.gewuyou.forgeboot.common.result.api.RequestIdProvider
import com.gewuyou.forgeboot.common.result.api.ResponseInformation
import com.gewuyou.forgeboot.common.result.api.ResultExtender
import com.gewuyou.forgeboot.common.result.impl.DefaultMessageResolver
import com.gewuyou.forgeboot.common.result.impl.DefaultRequestIdProvider
/**
* 统一响应封装类
*
* 该类用于统一系统中的响应格式提供基本地响应信息如状态码是否成功消息内容数据体等
* 并支持通过扩展器[ResultExtender]来扩展响应信息
*
* @param code 状态码
* @param success 是否成功
* @param message 响应消息
* @param data 响应数据体
* @param requestId 请求ID
* @param nameMap 响应字段名称映射表
*
* @since 2025-05-03 16:04:42
* @author gewuyou
*/
data class R<T>(
val code: Int,
val success: Boolean,
val message: String,
val data: T? = null,
val requestId: String? = null,
val nameMap: Map<String, String> = mapOf(
"code" to "code",
"success" to "success",
"message" to "message",
"data" to "data"
)
) {
/**
* 将响应对象转换为Map对象
*
* 此方法用于将响应对象转换为Map方便在不同层次中传递和处理响应信息
* 同时它允许通过[ResultExtender]来进一步扩展响应信息
*
* @param extenders 结果扩展器列表默认为空
* @return 转换后的Map对象
*/
fun toMap(extenders: List<ResultExtender> = emptyList()): MutableMap<String, Any?> {
val r = mutableMapOf(
"code" to code,
"success" to success,
"message" to message,
"data" to data
)
if (!requestId.isNullOrBlank()) {
r["requestId"] = requestId
}
extenders.forEach { it.extend(r) }
return r
}
companion object {
/**
* 创建成功地响应对象
*
* 该方法用于根据[ResponseInformation]创建一个成功地响应对象
* 它支持国际化消息解析和请求ID的生成并允许通过[ResultExtender]来扩展响应信息
*
* @param info 响应信息对象
* @param data 响应数据体默认为null
* @param messageResolver 消息解析器默认为[DefaultMessageResolver]
* @param requestIdProvider 请求ID提供者默认为[DefaultRequestIdProvider]
* @param extenders 结果扩展器列表默认为空
* @return 创建的响应对象
*/
fun <T> success(
info: ResponseInformation,
data: T? = null,
messageResolver: MessageResolver? = null,
requestIdProvider: RequestIdProvider? = null,
extenders: List<ResultExtender> = emptyList()
): R<T> {
val msg = (messageResolver ?: DefaultMessageResolver).resolve(
info.responseI8nMessageCode,
info.responseI8nMessageArgs
)
val reqId = (requestIdProvider ?: DefaultRequestIdProvider).getRequestId()
return R(info.responseCode, true, msg, data, reqId).also {
extenders.forEach { extender -> extender.extend(it.toMap()) }
}
}
/**
* 创建失败的响应对象
*
* 该方法用于根据[ResponseInformation]创建一个失败的响应对象
* 它支持国际化消息解析和请求ID的生成并允许通过[ResultExtender]来扩展响应信息
*
* @param info 响应信息对象
* @param data 响应数据体默认为null
* @param messageResolver 消息解析器默认为[DefaultMessageResolver]
* @param requestIdProvider 请求ID提供者默认为[DefaultRequestIdProvider]
* @param extenders 结果扩展器列表默认为空
* @return 创建的响应对象
*/
fun <T> failure(
info: ResponseInformation,
data: T? = null,
messageResolver: MessageResolver? = null,
requestIdProvider: RequestIdProvider? = null,
extenders: List<ResultExtender> = emptyList()
): R<T> {
val msg = (messageResolver ?: DefaultMessageResolver).resolve(
info.responseI8nMessageCode,
info.responseI8nMessageArgs
)
val reqId = (requestIdProvider ?: DefaultRequestIdProvider).getRequestId()
return R(info.responseCode, false, msg, data, reqId).also {
extenders.forEach { extender -> extender.extend(it.toMap()) }
}
}
/**
* 创建成功地响应对象
*
* 该方法用于创建一个简单的成功响应对象支持自定义状态码消息代码消息参数和数据体
* 它支持国际化消息解析和请求ID的生成并允许通过[ResultExtender]来扩展响应信息
*
* @param code 状态码默认为200
* @param messageCode 消息代码默认为"success"
* @param args 消息参数默认为null
* @param data 响应数据体默认为null
* @param messageResolver 消息解析器默认为[DefaultMessageResolver]
* @param requestIdProvider 请求ID提供者默认为[DefaultRequestIdProvider]
* @param extenders 结果扩展器列表默认为空
* @return 创建的响应对象
*/
fun <T> success(
code: Int = 200,
messageCode: String = "success",
args: Array<Any>? = null,
data: T? = null,
messageResolver: MessageResolver? = null,
requestIdProvider: RequestIdProvider? = null,
extenders: List<ResultExtender> = emptyList()
): R<T> {
val msg = (messageResolver ?: DefaultMessageResolver).resolve(messageCode, args)
val reqId = (requestIdProvider ?: DefaultRequestIdProvider).getRequestId()
return R(code, true, msg, data, reqId).also {
extenders.forEach { extender -> extender.extend(it.toMap()) }
}
}
/**
* 创建失败的响应对象
*
* 该方法用于创建一个简单的失败响应对象支持自定义状态码消息代码消息参数和数据体
* 它支持国际化消息解析和请求ID的生成并允许通过[ResultExtender]来扩展响应信息
*
* @param code 状态码默认为400
* @param messageCode 消息代码默认为"error"
* @param args 消息参数默认为null
* @param data 响应数据体默认为null
* @param messageResolver 消息解析器默认为[DefaultMessageResolver]
* @param requestIdProvider 请求ID提供者默认为[DefaultRequestIdProvider]
* @param extenders 结果扩展器列表默认为空
* @return 创建的响应对象
*/
fun <T> failure(
code: Int = 400,
messageCode: String = "error",
args: Array<Any>? = null,
data: T? = null,
messageResolver: MessageResolver? = null,
requestIdProvider: RequestIdProvider? = null,
extenders: List<ResultExtender> = emptyList()
): R<T> {
val msg = (messageResolver ?: DefaultMessageResolver).resolve(messageCode, args)
val reqId = (requestIdProvider ?: DefaultRequestIdProvider).getRequestId()
return R(code, false, msg, data, reqId).also {
extenders.forEach { extender -> extender.extend(it.toMap()) }
}
}
}
}

View File

@ -0,0 +1,13 @@
package com.gewuyou.forgeboot.common.result.impl
import com.gewuyou.forgeboot.common.result.api.MessageResolver
/**
*默认消息解析器
*
* @since 2025-05-03 16:21:43
* @author gewuyou
*/
object DefaultMessageResolver : MessageResolver {
override fun resolve(code: String, args: Array<Any>? ): String = code
}

View File

@ -0,0 +1,13 @@
package com.gewuyou.forgeboot.common.result.impl
import com.gewuyou.forgeboot.common.result.api.RequestIdProvider
/**
*默认请求ID提供商
*
* @since 2025-05-03 16:22:18
* @author gewuyou
*/
object DefaultRequestIdProvider : RequestIdProvider {
override fun getRequestId(): String = ""
}

View File

@ -1,3 +1,8 @@
extra {
// 标记为根项目
setProperty(ProjectFlags.IS_ROOT_MODULE, true)
}
dependencies {
}

View File

@ -1,5 +1,6 @@
dependencies {
implementation(project(Modules.Core.EXTENSION))
implementation(project(Modules.Common.RESULT_API))
compileOnly(libs.springBootStarter.web)
// Spring Boot WebFlux

View File

@ -24,6 +24,19 @@ public class I18nProperties {
*/
private String wildPathForLanguageFiles = "classpath*:i18n/**/messages";
/**
* 位置模式后缀
*/
private String locationPatternSuffix = ".properties";
public String getLocationPatternSuffix() {
return locationPatternSuffix;
}
public void setLocationPatternSuffix(String locationPatternSuffix) {
this.locationPatternSuffix = locationPatternSuffix;
}
public String getDefaultLocale() {
return defaultLocale;
}

View File

@ -1,9 +1,12 @@
package com.gewuyou.forgeboot.i18n.config
import com.gewuyou.forgeboot.common.result.api.MessageResolver
import com.gewuyou.forgeboot.i18n.filter.ReactiveLocaleResolver
import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.i18n.config.entity.I18nProperties
import com.gewuyou.forgeboot.i18n.resolver.I18nMessageResolver
import jakarta.servlet.http.HttpServletRequest
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
@ -54,6 +57,21 @@ open class I18nAutoConfiguration (
return messageSource
}
/**
* 创建并配置一个国际化的消息解析器
* 该方法通过Spring的条件注解有选择性地创建一个MessageResolver实例
* 主要用于解决国际化消息的解析问题
*
* @param forgebootI18nMessageSource 一个MessageSource实例用于解析国际化消息
* @return 返回一个MessageResolver实例用于在国际化的环境中解析消息
*/
@Bean
@ConditionalOnMissingBean(MessageResolver::class)
open fun i18nMessageResolver(@Qualifier(MESSAGE_SOURCE_BEAN_NAME) forgebootI18nMessageSource: MessageSource): MessageResolver {
return I18nMessageResolver(forgebootI18nMessageSource)
}
/**
* 扫描指定路径下的所有国际化属性文件路径
*
@ -65,16 +83,17 @@ open class I18nAutoConfiguration (
*/
private fun scanBaseNames(basePath: String): List<String> {
val baseNames: MutableList<String> = ArrayList()
val suffix = i18nProperties.locationPatternSuffix
log.info("开始扫描 I18n 文件 {}", basePath)
try {
val resources = PathMatchingResourcePatternResolver().getResources(
"$basePath*.properties"
"$basePath*$suffix"
)
for (resource in resources) {
val path = resource.uri.toString()
log.info("找到 I18n 文件路径: {}", path)
// 转换路径为 Spring 的 basename 格式(去掉 .properties 后缀)
val baseName = path.substring(0, path.lastIndexOf(".properties"))
val baseName = path.substring(0, path.lastIndexOf(suffix))
if (!baseNames.contains(baseName)) {
baseNames.add(baseName)
}
@ -150,6 +169,6 @@ open class I18nAutoConfiguration (
/**
* 消息源 bean 的名称
*/
const val MESSAGE_SOURCE_BEAN_NAME: String = "i18nMessageSource"
const val MESSAGE_SOURCE_BEAN_NAME: String = "forgebootI18nMessageSource"
}
}

View File

@ -0,0 +1,33 @@
package com.gewuyou.forgeboot.i18n.resolver
import com.gewuyou.forgeboot.common.result.api.MessageResolver
import org.springframework.context.MessageSource
import org.springframework.context.i18n.LocaleContextHolder
/**
* i18 n消息解析器
*
* 该类实现了MessageResolver接口用于解析国际化消息它依赖于Spring的MessageSource接口
* 来获取本地化消息文本并根据当前用户的区域设置来确定使用哪种语言的消息
*
* @since 2025-05-03 16:58:36
* @author gewuyou
*/
class I18nMessageResolver(
private val i18nMessageSource: MessageSource
) : MessageResolver {
/**
* 解析消息
*
* 根据给定的消息代码和可选的参数数组解析并返回具体的消息字符串
* 这个方法允许在不同的上下文中重用消息解析逻辑并可以根据需要提供不同的实现
*
* @param code 消息代码用于标识特定的消息类型或模板
* @param args 可选的消息参数数组用于替换消息模板中的占位符
* @return 解析后的消息字符串
*/
override fun resolve(code: String, args: Array<Any>?): String {
// 使用Spring的MessageSource来获取与当前区域设置相匹配的消息文本
return i18nMessageSource.getMessage(code, args, LocaleContextHolder.getLocale())
}
}

View File

@ -1,5 +1,7 @@
dependencies {
implementation(project(Modules.Core.EXTENSION))
implementation(project(Modules.Common.RESULT_API))
// Spring Cloud OpenFeign (Compile Only)
// https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign
compileOnly(libs.springCloudStarter.openfeign)

View File

@ -1,11 +1,13 @@
package com.gewuyou.forgeboot.trace.config
import com.gewuyou.forgeboot.common.result.api.RequestIdProvider
import com.gewuyou.forgeboot.trace.config.entities.TraceProperties
import com.gewuyou.forgeboot.trace.decorator.RequestIdTaskDecorator
import com.gewuyou.forgeboot.trace.filter.ReactiveRequestIdFilter
import com.gewuyou.forgeboot.trace.filter.RequestIdFilter
import com.gewuyou.forgeboot.trace.filter.WebClientRequestIdFilter
import com.gewuyou.forgeboot.trace.interceptor.FeignRequestIdInterceptor
import com.gewuyou.forgeboot.trace.provider.TraceRequestIdProvider
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
@ -51,6 +53,16 @@ open class TraceAutoConfiguration {
open fun reactiveRequestIdFilter(traceProperties: TraceProperties): ReactiveRequestIdFilter =
ReactiveRequestIdFilter(traceProperties)
/**
* 请求ID提供者用于生成请求ID
*
* 该提供者用于生成请求ID默认为TraceRequestIdProvider
* @return RequestIdProvider实例
*/
@Bean
@ConditionalOnMissingBean(RequestIdProvider::class)
open fun traceRequestIdProvider(): TraceRequestIdProvider = TraceRequestIdProvider()
/**
* Feign 拦截器仅当 Feign 存在时生效
*

View File

@ -0,0 +1,23 @@
package com.gewuyou.forgeboot.trace.provider
import com.gewuyou.forgeboot.common.result.api.RequestIdProvider
import com.gewuyou.forgeboot.trace.util.RequestIdUtil
/**
*跟踪请求ID提供商
*
* @since 2025-05-03 17:26:46
* @author gewuyou
*/
class TraceRequestIdProvider: RequestIdProvider {
/**
* 获取请求ID
*
* 返回一个唯一的字符串标识符作为请求ID
*
* @return 请求ID的字符串表示
*/
override fun getRequestId(): String {
return RequestIdUtil.getRequestId()
}
}

View File

@ -40,6 +40,9 @@ kotlinxEcosystem = ["kotlinxDatetime", "kotlinxSerialization", "kotlinxCoroutine
[plugins]
# 应用 Java 插件,提供基本的 Java 代码编译和构建能力
java = { id = "java" }
# 应用 Java Library 插件,支持库开发,提供 API 和实现分离的能力
javaLibrary = { id = "java-library" }
kotlinPluginSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin-version" }
axionRelease = { id = "pl.allegro.tech.build.axion-release", version.ref = "axion-release-version" }
# 应用 Spring Boot 插件,提供 Spring Boot 应用的开发和运行能力

View File

@ -63,3 +63,17 @@ include(
)
project(":forgeboot-trace").name = "forgeboot-trace-spring-boot-starter"
//endregion
//region module common
include(
"forgeboot-common",
":forgeboot-common:forgeboot-common-result",
":forgeboot-common:forgeboot-common-result:forgeboot-common-result-api",
":forgeboot-common:forgeboot-common-result:forgeboot-common-result-impl",
// ":forgeboot-common:forgeboot-common-result:forgeboot-common-result-extension",
)
project(":forgeboot-common").name = "forgeboot-common"
project(":forgeboot-common:forgeboot-common-result").name = "forgeboot-common-result"
project(":forgeboot-common:forgeboot-common-result:forgeboot-common-result-api").name = "forgeboot-common-result-api"
project(":forgeboot-common:forgeboot-common-result:forgeboot-common-result-impl").name = "forgeboot-common-result-impl"
//endregion