我的应用程序遇到许多不同的dbs,db取决于查询字符串参数。我有一个DatabaseConfigLocator,它接受字符串并返回配置,它工作得很好。我的问题是我想在我的控制器中隐式地为每个请求进行配置。我尝试了两种方法。
class MyController extends Controller{
implicit def dbConfig(implicit request: RequestHeader): DatabaseConfig[JdbcProfile] = DatabaseConfigLocator.get[JdbcProfile](request.getQueryString("dbName")
}
除非我将其更改为具有相同类型的implicit val
,否则我必须编译这个dosn,但是我需要每次请求重新检查查询字符串,所以我不认为{{1将会工作
另一种方法是创建一个动作
implicit val
但隐含在块的范围内不可用,我无法找到任何方式将其作为隐式传递。
我的目标是能够做这样的事情
object IODBAction extends ActionBuilder[Request]{
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
implicit def dbConfig(implicit request: RequestHeader): DatabaseConfig[JdbcProfile] = DatabaseConfigLocator.get[JdbcProfile]("blah")
block(request)
}
}
或者如果提供者可以在实例化时获得隐含的更好的
class MyController extends Controller {
def create = {
Action.async {
request =>
ApiResponse {
for {
id <- aProvider.save(validRegistrationRequest.toVisitor)
} yield id
}
}
}
}
class aProvider {
def save(v: Visitor)(implicit dbConfig: DatabaseConfig[JdbcProfile]): ApiResponse[VisitorId]
}
有关如何处理此问题或是否可以使用播放框架的任何建议?
答案 0 :(得分:1)
不幸的是,我担心你会遇到一个接受单个参数的动作,所以你需要坚持标准游戏&#34;动作组合&#34;图案。这在play docs中有相当广泛的记载。
我定义了一个&#34; Context&#34;像这样:
case class Context(dbConfig: DatabaseConfig[JDBCProfile], request: Request[A])
extends WrappedRequest(request)
然后创建一个这样的自定义动作构建器:
object DBIOAction extends ActionBuilder[Context]{
def invokeBlock[A](request: Request[A], block: (Context[A]) => Future[Result]) = {
val dbConfig = DatabaseConfigLocator.get[JdbcProfile]("blah")
val context = Context(dbConfig, request)
block(context)
}
}
然后您应该能够像这样使用它:
def index = DBIOAction { implicit context =>
// do some stuff. return a result
}
为了简单起见,我将隐式上下文传递给您的服务方法,也许从上下文中提取dbConfig并将其余部分传递给您的DAO。
class FunService {
def getSomeData(param1: String)(implicit context: Context) = {
// do some work, perhaps using context.dbConfig
}