使用Play框架的缓存API在多语言网站中缓存一个操作

20
为了对给定的标签和语言缓存操作一段时间,我编写了以下帮助方法(其中label是我为我的操作命名的名称):
def cacheResponseFor(label: String, duration: Int)(action: EssentialAction) = { 
   Cached({r: RequestHeader => (label + getLanguage(r))}, duration){ action }
}

def getLanguage(request: RequestHeader): String = {
   request.cookies
     .get(helpers.SessionHelpers.LANGUAGE_SESSION)
        .map(_.value)
          .getOrElse(helpers.LanguageHelpers.FRENCH)
}

但是我遇到了一些奇怪的问题,当我尝试将一个Action缓存60秒,并在此期间从法语切换到英语等其他语言时,我仍然会在60秒内获得法语版本,然后才会切换到英文。

经过调查,我发现getLanguage方法并没有在每次调用该操作时都被调用,好像只有在缓存周期结束后才会对键进行评估。

这不对,我希望每次请求页面时都会调用cacheResponseFor,使用getLanguage来评估语言,并获取正确的缓存版本,即我应该最终获得两个缓存操作(每种语言一个)。

我有遗漏什么吗?


看起来非常奇怪,可能是一个玩笑性质的错误。你检查了缓存版本是从哪里来的吗?它是在客户端缓存(服务器将返回NotModified)还是在服务器端缓存? - Hüseyin Zengin
它应该被缓存在服务器端,服务器返回200 Ok。 - Peter
你的LANGUAGE_SESSION是否还未更改为新请求,因此使用之前设置的缓存?如果已经设置了LANGUAGE_SESSION,则不会触发getOrElse。 - Marco Aurelio
2个回答

1

我不知道您正在面临什么问题,但我做了一个小的概念验证,一点问题也没有。

package controllers

import play.api.cache.Cached
import play.api.mvc.{Action, Controller, EssentialAction, RequestHeader}

object Caches {
  import play.api.Play.current

  def cacheResponseFor(label: String, duration: Int)(action: EssentialAction) = {
    Cached({r: RequestHeader => label + getLanguage(r)}, duration){ action }
  }

  def getLanguage(request: RequestHeader): String = {
    request.cookies
      .get("language")
      .map(_.value)
      .getOrElse("fr")
  }
}

class CachedApplication () extends Controller {

  import Caches._

  def index = cacheResponseFor("homePage", 60) {
    Action { implicit req =>
      getLanguage(req) match {
        case "fr" =>
          Ok("Bonjour le monde")
        case _ =>
          Ok("Hello world")
      }
    }
  }
}

你在60秒的时间内切换了语言吗? - Peter
是的,更改 cookie 并重新加载页面。 - Jonas Anso
我甚至调试了它,发现针对未缓存的请求getLanguage被调用了两次,而缓存请求则只调用了一次。 - Jonas Anso
奇怪,我会在周末尝试检查一下,然后告诉你。 - Peter

1
也许问题出在getLanguage方法上。按照文档的建议尝试以下操作:
def getLanguage(request: RequestHeader): String = {
    request.acceptLanguages
           .map(_.code)
           .headOption
           .getOrElse(helpers.LanguageHelpers.FRENCH)
}

此外,看一下Controller.request2lang()方法,看看它是否对您有帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接