请求之间的Application类变量不可用

时间:2016-03-02 02:17:48

标签: playframework-2.4 scala-2.11

我有一个应用程序控制器,它有两种方法。在第一种方法中,我访问数据库并检索表单的下拉元素列表。我将检索到的元素存储在类级变量中。在第二种方法中,如果出现错误,则显示表单,否则显示结果。问题是我的类级变量返回空。

    class Application extends Controller {

      var appList = Seq[AppDetail]()
      var countryList = Seq[Country]()

    def home(page:Int,filter: String): Action[AnyContent] = Action.async { implicit request =>

    val futures = for {
            appDetails <- AppDetailsDAO.listAll() //DB retrieve
            countries <- CountriesDAO.listAll()   //DB retrieve
          } yield (appDetails, countries)

          futures.map{case (appDetails, countries) => {
            appList = appDetails
            countryList = countries
            Ok(appList, countryList)
          }

       }

       def result(page:Int, filter: String): Action[AnyContent] = Action.async { implicit request =>

    analyticForm.bindFromRequest.fold(
      formWithErrors => {
        Future.successful(BadRequest(html.home(formWithErrors, appList,  countryList)) //appList, countryList returns empty
      },
      analyticData => {
     Ok(appList, countryList) //appList, countryList returns empty
      }
    }
   }

1 个答案:

答案 0 :(得分:1)

Play是一个RESTful框架。这意味着,除其他外,您不应在两个请求之间共享信息。请求总是无状态。

要解决您的问题,您只需在两个操作中获取appListcountryList即可。同时删除控制器中的两个var。尽可能避免scala中的可变变量(尽管在某些情况下它们可能很有用)。请参阅Daniel C. Sobral关于the difference between var and val的答案。

未经测试的代码:

class Application extends Controller {

  def home(page:Int,filter: String): Action[AnyContent] = Action.async { implicit request =>
    fetchDb.map{case (appDetails, countries) => {
      appList = appDetails
      countryList = countries
      Ok(appList, countryList)
    }}
  }

  def result(page:Int, filter: String): Action[AnyContent] = Action.async { implicit request =>
    fetchDb.map{case (appDetails, countries) => {
      analyticForm.bindFromRequest.fold(
        formWithErrors => {
          BadRequest(html.home(formWithErrors, appList,  countryList))
        },
        analyticData => {
          Ok(appList, countryList) //appList, countryList returns empty
        }
      )
    }}
  }

  def fetchDb = {
    val fAppDetails = AppDetailsDAO.listAll()
    val fCountries = CountriesDAO.listAll()

    for {
      appDetails <- fAppDetails
      countries <- fCountries
    } yield (appDetails, countries)
  }
}

附注:您可能已经注意到我在Future之外创建了fetchDb个实例以进行理解。这是因为for comprehension只是嵌套平面地图的另一种表示。这意味着countriesappDetails完成之前不会运行。期货将按顺序运行。如果你把它们放在理解之外,它们就会并行运行。