You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Micronaut-Core:如何不使用@Endpoint注解创建动态端点

完全可以不使用@Endpoint注解创建动态端点,你可以借助Micronaut自带的路由注册API在应用启动时完成动态端点的加载,具体实现方案如下:

核心实现逻辑

你不需要依赖注解声明端点,直接注入Router和RouteBuilder两个核心组件,在启动事件触发、完成描述文件解析后,调用API注册路由即可:

import io.micronaut.context.event.StartupEvent
import io.micronaut.context.event.ShutdownEvent
import io.micronaut.runtime.event.annotation.EventListener
import io.micronaut.web.router.Router
import io.micronaut.web.router.RouteBuilder
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.HttpMethod
import io.micronaut.http.MediaType
import jakarta.inject.Singleton
import reactor.core.publisher.Mono
import reactor.core.scheduler.Schedulers

@Singleton
class DynamicEndpointLoader(
    private val router: Router,
    private val routeBuilder: RouteBuilder
) {

    @EventListener
    internal fun onStartupEvent(event: StartupEvent) {
        // 1. 读取/resources下所有自定义描述文件
        // 2. 调用你已开发完成的解析器,拿到所有解析后的MyDescription对象
        val endpointConfigs: List<MyDescription> = yourParseLogic()

        endpointConfigs.forEach { config ->
            // 解析你配置里的HTTP方法、请求路径
            val (method, path) = parseEndpointConfig(config.getEndpoint()) // 返回HttpMethod.GET、"/myapi/customendpoint/version"这类结果
            
            // 注册路由
            routeBuilder.addRoute(
                method,
                path,
                { _: HttpRequest<*> ->
                    Mono.fromCallable {
                        // 执行配置里的shell命令,拿到返回结果
                        val executeResult = runYourSshCommand(config.getCommand())
                        // 渲染输出模板,替换$RESULT变量
                        val output = config.getOutput().replace("\$RESULT", executeResult)
                        // 返回响应
                        HttpResponse.ok(output).contentType(MediaType.APPLICATION_JSON)
                    }.subscribeOn(Schedulers.boundedElastic()) // 阻塞的SSH操作放到IO线程池执行,避免占用Netty IO线程
                }
            ).produces(MediaType.APPLICATION_JSON)
        }

        // 注册所有路由到运行时,立即生效
        router.addRoutes(routeBuilder.build())
    }

    @EventListener
    internal fun onShutdownEvent(event: ShutdownEvent) {
        // 按需实现路由卸载、资源释放逻辑
    }
}

注意事项

  • 如果需要支持路径参数、请求参数匹配,RouteBuilder也支持类似/myapi/{userId}/info的占位符写法,参数可以从HttpRequest对象中提取
  • 建议给命令执行增加超时控制,避免请求长期挂起
  • 可以根据需要为不同的动态端点设置不同的响应Content-Type、权限校验逻辑,只需要在处理函数中对应实现即可

内容的提问来源于stack exchange,提问作者Thraax.Session

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 16:24:01