请求之间的应用程序 class 变量不可用

Non availability of Application class variable between requests

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

    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
      }
    }
   }

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)
  }
}

旁注:您可能注意到我在 for 理解之外的 fetchDb 中创建了 Future 实例。这是因为 for comprehension 只是嵌套平面映射的另一种表示形式。这意味着 countriesappDetails 完成之前不会 运行。期货将 运行 依次。如果您将它们放在 for comprehension 之外,它们将 运行 并行。