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

在Play Framework中使用Tapir Router时移除JSR330依赖实现单例

在Play Framework中实现Tapir Router单例(移除JSR330依赖)

下面提供三种无需JSR330依赖的实现方案,确保Router以单例运行:

方案1:Play原生依赖注入绑定单例

利用Play自带的Guice集成实现单例绑定,无需额外库:

  1. 移除ApiRouter类上的@Singleton注解
  2. 创建自定义模块类,在其中绑定ApiRouter为饿汉式单例:
import com.google.inject.AbstractModule
import play.api.inject.Module

class ApiModule extends AbstractModule with Module {
  override def configure(): Unit = {
    // asEagerSingleton确保启动时初始化实例,避免重复创建
    bind(classOf[ApiRouter]).asEagerSingleton()
  }
}
  1. 在conf/application.conf中注册该模块:
play.modules.enabled += "com.yourpackage.ApiModule"

方案2:手动实现Scala单例模式

方式A:直接使用Scala对象

将ApiRouter改为Scala对象(本身就是JVM级单例):

import sttp.tapir.server.play.PlayServerInterpreter
import play.api.mvc.Router

object ApiRouter {
  // 初始化Tapir端点并生成路由
  val router: Router = PlayServerInterpreter().toRoutes(/* 你的Tapir端点集合 */)
}

在conf/routes中直接引用:

->  /api  ApiRouter.router

注意:若Router依赖其他组件,需确保依赖也是单例或已提前初始化。

方式B:懒加载单例类

若需要保留类的结构(比如有构造参数),可实现懒加载单例:

class ApiRouter(yourDependency: YourDependency) {
  val router: Router = PlayServerInterpreter().toRoutes(/* 端点集合 */)
}

object ApiRouter {
  private lazy val instance: ApiRouter = new ApiRouter(/* 初始化单例依赖 */)
  def getInstance: ApiRouter = instance
}

后续通过ApiRouter.getInstance获取单例实例即可。

方案3:直接绑定单例端点路由

跳过单独的Router类,直接在单例对象中定义并生成Tapir路由:

import sttp.tapir._
import sttp.tapir.server.play.PlayServerInterpreter
import play.api.mvc._
import scala.concurrent.Future

object ApiEndpoints {
  // 定义端点
  private val helloEndpoint = endpoint.get.in("hello").out(stringBody)
  
  // 生成单例路由
  val helloRoute: Handler = PlayServerInterpreter().toRoute(helloEndpoint) { _ =>
    Future.successful(Right("Hello from Tapir!"))
  }
}

在conf/routes中绑定:

->  /api  ApiEndpoints.helloRoute

内容的提问来源于stack exchange,提问作者zella

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:45:43