【问题标题】:No cache header with annotation没有带注释的缓存标头
【发布时间】:2013-07-17 22:25:23
【问题描述】:

为了在控制器中设置没有缓存的响应,您可以这样做:

$response = new Response();
$result = $this->renderView(
        'AcmeDemoBundle:Default:index.html.twig',
         array('products' => $products, 'form' => $form->createView()));
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
$response->setContent($result);

return $response;

但是使用注解,保证每个方法的结果都一样,怎么办?

我试过了,但继续保存缓存,如果我使用浏览器的后退按钮保留缓存:

/**
 * @Cache(maxage="0", vary="no-cache, must-revalidate, no-store", smaxage="0", expires="now", public="false")
 */
class DefaultController extends Controller
{
/**
 * Homepage: show products
 * 
 * @Route("/", name="homepage")
 * @Template
 */
public function indexAction()
{
    $sessionCart = $this->get('demo');
    $filters = $sessionCart->getFilters($this->getDoctrine()->getEntityManager());
    $products = $this->getDoctrine()->getRepository('AcmeDemoBundle:Product')->search($filters);
    $form = $this->createForm(new FilterType, $filters);

    return array('products' => $products, 'form' => $form->createView());
}

如果按照文档所述强加:

@Cache(vary=["no-cache", "must-revalidate", "no-store"]...

给了我一个不期望“[”的语法错误,所以我按照上面的方法尝试了。

【问题讨论】:

  • 通常哈希图在注释中用大括号定义。试试看:@Cache(vary={"..."})
  • 我试过了,和使用一样:vary="no-cache, must-revalidate, no-store"在response-header中我总能找到vary no-cache,must-revalidate,no-store,但是继续拿缓存
  • 妈妈,你得到响应中的标题了吗?
  • 我也面临这个问题。您可以在响应中看到变化的标头,但它实际上并没有强制对 Vary 标头逻辑进行缓存(数组中的第一个标头除外)。让 @Cache 注释与变量一起使用的唯一方法是执行 @Cache(vary = "Accept-Encoding, X-Foo, X-Foo2")

标签: symfony symfony-2.3


【解决方案1】:

你混合了两件事。在您的第一个 sn-p 中,您正在设置缓存控制标头,但要使用注释来设置 Vary 标头。但是VaryCache-Control 标头完全不同,no-cache, must-revalidate, no-store 应该位于其中。 Vary 表示响应可能会根据请求(即 Cookie)而变化。请参阅此答案以了解:https://stackoverflow.com/a/1975677/2084176

在您的情况下(无缓存),如果没有缓存头,您可以依赖 symfony 设置的on the defaults

Symfony2 自动设置一个合理且保守的 Cache-Control 标头,当开发者没有设置时,遵循以下规则:

  • 如果没有定义缓存头(Cache-ControlExpiresETagLast-Modified),则Cache-Control设置为no-cache,表示响应不会被缓存;

编辑:如果您需要为每个控制器操作设置缓存标头,您可以使用kernel.response 事件。创建一个对此事件做出反应的侦听器,并使用适当的缓存控件修改响应。

namespace Acme\DemoBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

class AcmeCacheListener
{
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $response = $event->getResponse();

        $response->headers->addCacheControlDirective('no-cache', true);
        $response->headers->addCacheControlDirective('max-age', 0);
        $response->headers->addCacheControlDirective('must-revalidate', true);
        $response->headers->addCacheControlDirective('no-store', true);
    }
}

在你的services.yml

services:
    kernel.listener.your_listener_name:
        class: Acme\DemoBundle\EventListener\AcmeCacheListener
        tags:
            - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }

【讨论】:

  • 感谢您的澄清,但如果我在按下后退按钮时未设置任何内容,浏览器会保留缓存,但如果我设置$response->headers->addCacheControlDirective('no-cache', true); $response->headers->addCacheControlDirective('max-age', 0); $response->headers->addCacheControlDirective('must-revalidate', true); $response->headers->addCacheControlDirective('no-store', true);,浏览器不会每次都保留缓存我按下后退按钮重新加载页面。
  • 您不得设置任何缓存标头来将此默认设置付诸实施。没有 Vary 标题,什么都没有。但是后退按钮是浏览器特有的行为,你不能赌它。 no-store 在大多数情况下应该可以工作,但是嗯。这是另一个很好的答案:stackoverflow.com/a/866866/2084176
  • 我在 chrome 和 firefox 上都试过了,结果都一样。如果我按照你说的设置no-store 不再占用缓存。那么问题是:是否有可能在注释上设置no-store 或在控制器中至少设置一次?
  • 每次操作都需要这个吗?
  • 是的,我有一个购物车,数据放在会话中,每次我按浏览器上的后退按钮都会丢失购物车的产品,直到您重新加载页面!
【解决方案2】:

我猜主要问题是 Cache 注释没有 no-cache、no-store 和 must-revalidate 选项。我无法解释为什么。 作为对帕特里克的回答的补充,如果您有多个控制器并且您只想将标头应用于一个,您可以检查侦听器中的控制器类,如下所示:

class AcmeCacheListener
{
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $controller = $event->getRequest()->attributes->get('_controller');
        $requiredController = "Acme\Controller\DefaultController";
        if( substr($controller, 0,strlen($requiredController)) == $requiredController) {

            $response = $event->getResponse();
            $response->headers->addCacheControlDirective('no-cache', true);
            $response->headers->addCacheControlDirective('max-age', 0);
            $response->headers->addCacheControlDirective('must-revalidate', true);
            $response->headers->addCacheControlDirective('no-store', true);
         }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多