feat: 新增 8 个语言客户端 SDK

- PHP 客户端 (kenaito-conf-php-client)
- .NET 客户端 (kenaito-conf-dotnet-client)
- C 客户端 (kenaito-conf-c-client)
- C++ 客户端 (kenaito-conf-cpp-client)
- Lua 客户端 (kenaito-conf-lua-client)
- Kotlin 客户端 (kenaito-conf-kotlin-client)
- Rust 客户端 (kenaito-conf-rust-client)
- Ruby 客户端 (kenaito-conf-ruby-client)

每个客户端包含完整的 SDK 实现和 demo 示例,支持:
- 配置拉取(全量/增量)
- AES-128-CBC 解密
- 本地缓存
- 变更回调
- Token 认证

更新根目录 README.md:
- 技术栈列表新增 8 种语言
- 项目结构新增 16 个目录
- 客户端接入章节新增 8 个使用示例
This commit is contained in:
2026-03-05 21:14:42 +08:00
parent 2f5c343347
commit 4c3648cf7f
40 changed files with 2824 additions and 2 deletions
@@ -0,0 +1,14 @@
plugins {
kotlin("jvm") version "1.9.0"
application
}
repositories { mavenCentral() }
dependencies {
implementation(files("../kenaito-conf-kotlin-client/build/libs/kenaito-conf-kotlin-client-1.0.0.jar"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
}
application { mainClass.set("demo.AppKt") }
@@ -0,0 +1 @@
rootProject.name = "kenaito-conf-kotlin-client-demo"
@@ -0,0 +1,49 @@
import kenait.conf.Config
import kenait.conf.ConfigClient
fun main() {
val configValues = mutableMapOf(
"database.host" to (System.getenv("DATABASE_HOST") ?: "192.168.1.1"),
"database.port" to (System.getenv("DATABASE_PORT") ?: "8888"),
"database.name" to (System.getenv("DATABASE_NAME") ?: "xxxx"),
"database.user" to (System.getenv("DATABASE_USER") ?: "xxxx"),
"database.password" to (System.getenv("DATABASE_PASSWORD") ?: "xxxxxxxx"),
)
val config = Config(
baseUrl = System.getenv("KENAITO_BASE_URL") ?: "http://localhost:8080",
appName = System.getenv("KENAITO_APP_NAME") ?: "kenaito-springboot-demo",
env = System.getenv("KENAITO_PROFILE") ?: "daily",
version = System.getenv("KENAITO_VERSION") ?: "latest",
token = System.getenv("KENAITO_TOKEN") ?: "",
syncInterval = (System.getenv("KENAITO_SYNC_INTERVAL") ?: "30").toInt(),
cacheDir = System.getenv("KENAITO_CACHE_DIR") ?: ".",
)
val client = ConfigClient(config)
client.onChange { changed ->
changed.forEach { (k, v) ->
if (configValues.containsKey(k)) {
configValues[k] = v
System.err.println("config updated: $k = $v")
}
}
}
try {
client.start()
val remote = client.getAll()
configValues.keys.forEach { k ->
remote[k]?.let { configValues[k] = it }
}
System.err.println("loaded ${remote.size} configs from remote")
} catch (e: Exception) {
System.err.println("failed to init config client: ${e.message}")
}
println("Current configs:")
configValues.forEach { (k, v) -> println(" $k = $v") }
println("\nListening for config changes... (press Ctrl+C to stop)")
Thread.currentThread().join()
}