如何在控制器中正确传递参数?

How correctly pass parameters in controllers?

我是 Play Framework 的新人,需要一些建议。

在我的项目中,我发送了 AJAX 请求,但不幸的是 Play Framework 引发了错误,您可以在下面看到该错误。从错误消息中,您可以注意到该问题最有可能出现在控制器中。我的错误在哪里?如何修复此错误?

[error] application - 

! @79mg8k016 - Internal server error, for (GET) [/] ->

play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:

1) No implementation for play.api.db.Database was bound.
  while locating play.api.db.Database
    for the 1st parameter of controllers.GetValuesController.<init>(GetValuesController.scala:14)
  while locating controllers.GetValuesController
    for the 4th parameter of router.Routes.<init>(Routes.scala:33)
  at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon)

1 error]
    at play.core.server.DevServerStart$$anon.reload(DevServerStart.scala:186)
    at play.core.server.DevServerStart$$anon.get(DevServerStart.scala:124)
    at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:241)
    at play.core.server.AkkaHttpServer.$anonfun$createServerBinding(AkkaHttpServer.scala:138)
    at akka.stream.impl.fusing.MapAsyncUnordered$$anon.onPush(Ops.scala:1304)
    at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:519)
    at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:482)
    at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:378)
    at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:588)
    at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:472)
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) No implementation for play.api.db.Database was bound.
  while locating play.api.db.Database
    for the 1st parameter of controllers.GetValuesController.<init>(GetValuesController.scala:14)
  while locating controllers.GetValuesController
    for the 4th parameter of router.Routes.<init>(Routes.scala:33)
  at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:121):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon)

控制器好像出了点问题。我的错误在哪里,如何解决?

我使用:

JDK 1.8.0_181
SBT 0.13.5
Scala 2.12
Play Framework 2.6.20

路线:

GET /get_values controllers.GetValuesController.get_data_from_db(start_date_time:String, end_date_time:String, city_name:String)

GetValuesController.scala:

package controllers

import javax.inject._

import akka.actor.ActorSystem
import play.api.Configuration
import play.api.mvc.{AbstractController, ControllerComponents}
import play.api.libs.ws._
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future, Promise}
import services._
import play.api.db.Database

class GetValuesController@Inject()(db: Database, conf: Configuration, ws: WSClient, cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends AbstractController(cc) {

    def get_data_from_db(start_date_time: String, end_date_time: String, city_name: String) = Action.async {
        getValue(1.second, start_date_time: String, end_date_time: String, city_name: String).map {
            message => Ok(message)
        }
    }

    private def getValue(delayTime: FiniteDuration, start_date_time: String, end_date_time: String, city_name: String): Future[String] = {
        val promise: Promise[String] = Promise[String]()

        val service: GetValuesService = new GetValuesService(db)

        actorSystem.scheduler.scheduleOnce(delayTime) {
            promise.success(service.get_values(start_date_time, end_date_time, city_name))
        }(actorSystem.dispatcher)

        promise.future
    }
}

GetValuesService.scala:

package services

import play.api.db.Database
import play.api.libs.json._

class GetYoutubeSpeedValuesService(db: Database) {

    def get_youtube_speed_values(start_date_time: String, end_date_time: String, city_name: String): String ={


        val SQL_STATEMENT = "SELECT " +
        "table_name.\"Stamper\" AS DATE_TIME, " +
        "table_name.\"CITY\" AS CITY, " +
        "MAX(table_name.avg) AS MAX_SPEED " +
        "FROM table_name" +
        "WHERE table_name.\"CITY\"='" +  city_name + "' " +
        "AND (table_name.\"Stamper\" BETWEEN '" + start_date_time + "' AND '" + end_date_time + "') " +
        "GROUP BY table_name.\"Stamper\", table_name.\"CITY\";"

        val connection = db.getConnection()

        var json_array = Json.arr()

        try {
            val query = connection.createStatement.executeQuery(SQL_STATEMENT)
            while (query.next()) {
                val json_object = Json.obj(
                    "DATE_TIME" -> query.getString(1),
                    "CITY" -> query.getString(2),
                    "MAX_SPEED" -> query.getString(3)
                )
                json_array +:= json_object
            }
        } finally {
            connection.close()
        }

        println(json_array)

        json_array.toString()
    }
}

application.conf:

db.postgres.driver=org.postgresql.Driver
db.postgres.url="jdbc:postgresql://host:port/database_name"
db.postgres.username = "username"
db.postgres.password = "password"

Javascript:

$.ajax({
        type: "POST",
        url: "http://localhost:9000/get_values",
        data: {
            start_date_time: '2018-10-01 00:00:00',
            end_date_time: '2018-10-31 23:00:00',
            city_name: 'London'
        },
        success: function (result) {
            console.log(result);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log("jqXHR: " + jqXHR);
            console.log("textStatus: " + textStatus);
            console.log("errorThrown: " + errorThrown);
        }
    });

错误:

Action Not Found
For request 'POST /get_values'

同时控制器现在可以正常工作了!如果我打电话让我们说 url: http://localhost:9000/get_values?start_date_time=2018-10-01%2000:00:00&end_date_time=2018-10-31%2023:00:00&city_name=London 它 return 我 JSON 数据。

嗯,终于找到问题所在了。问题出在 application.conf 文件中。在我的例子中,我使用了下一个数据库配置:

db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://host:port/database_name"
db.default.username = "username"
db.default.password = "password"

同样在 AJAX 代码中我删除了这部分:type: "POST"