挂毯4:资产高速缓存控制? [英] Tapestry 4: Asset Cache Control?

查看:132
本文介绍了挂毯4:资产高速缓存控制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用挂毯4,每当我们推释放改变任何资源(图片,样式表,JS库),我们得到的问题,因为用户仍然有旧版本的资产在他们的浏览器缓存。我想设置一些简单的方法来允许缓存,但强制执行新的资产下载时,我们更新应用程序。简单地完全不允许缓存资产不是一个可接受的解决方案。

I use Tapestry 4, and whenever we push a release that changes any assets (image, style sheet, JS library), we get problems because users still have the old version of the asset in their browser cache. I'd like to set up some easy way to allow caching, but force a new asset download when we update the application. Simply disallowing caching entirely for assets is not an acceptable solution.

我看不到这样做的任何现有的机制,但我盘算,可能有一些方法来告诉挂毯的版本号添加到URL,像这样:

I couldn't see any existing mechanism for doing this, but I was figuring that there might be some way to tell Tapestry to add the build number to the URL, something like this:

http://www.test.com/path/到/的/资产/ asset.jpg?12345

这样,每一个新版本将使它看起来像一个不同的资产给最终用户。

That way, every new build would make it look like a different asset to the end user.

挂毯是否提供了一种简单的方法来解决缓存问题是我不知道的?如果不是,怎么会去修改由挂毯生成的网址是什么?而如何将在code负责这样做,得到的内部版本号? (我能得到的内部版本号为一个Spring bean,例如,但如何将新的URL建设机制得到它?)

Does Tapestry provide an easy way to solve the cache problem that I'm not aware of? If not, how would one go about modifying the URL generated by Tapestry? And how would the code responsible for doing that get the build number? (I could get the build number into a Spring bean, for example, but how would the new URL building mechanism get at it?)

推荐答案

炖这个问题很长一段时间后,我终于解决了它自己。此解决方案假定您有挂毯弹簧库在你的项目。

After stewing about this problem for a long time, I eventually solved it myself. This solution assumes you have the tapestry-spring library in your project.

在我的情况,我有一个Spring bean包含我的一些应用程序的全局属性的:

In my case, I have a Spring bean that contains some of my application's global properties:

package myapp;

public class AppProperties {
    private String build;

    public String getBuild() {
        return build;
    }

    public void setBuild(String build) {
        this.build = build;
    }

    // other properties
}

在Spring配置

声明这个bean:

Declare this bean in your Spring configuration:

<bean id="appProperties" class="myapp.AppProperties">
    <property name="build" value="@BUILD_NUMBER@"/>
</bean>

您可以设置您的Ant构建脚本与实际的更换次数 @BUILD_NUMBER @ (见的Copy 在细节Ant手册任务)。

You can set up your Ant build script to replace @BUILD_NUMBER@ with the actual number (see the Copy task in the Ant manual for details).

现在创建一个类,将包裹 IAsset 和清偿的版本号上的网址:

Now create a class that will wrap IAssets and tack the build number onto the URL:

package myapp;

import java.io.InputStream;

import org.apache.hivemind.Location;
import org.apache.hivemind.Resource;
import org.apache.tapestry.IAsset;

public class BuildAwareAssetWrapper implements IAsset {
    private IAsset wrapped;
    private String build;

    public BuildAwareAssetWrapper(IAsset wrapped, String build) {
        this.wrapped = wrapped;
        this.build = build;
    }

    public String buildURL() {
        return addParam(wrapped.buildURL(), "build", build);
    }

    public InputStream getResourceAsStream() {
        return wrapped.getResourceAsStream();
    }

    public Resource getResourceLocation() {
        return wrapped.getResourceLocation();
    }

    public Location getLocation() {
        return wrapped.getLocation();
    }

    private static String addParam(String url, String name, String value) {
        if (url == null) url = "";
        char sep = url.contains("?") ? '&' : '?';
        return url + sep + name + '=' + value;
    }
}

接下来,我们需要做挂毯包裹的所有资产与我们的包装。在 AssetSourceImpl 类是负责提供 IAsset 实例挂毯。我们将扩展该类并覆盖 findAsset()方法,使我们可以与包装类包裹创造的资产:

Next, we need to make Tapestry wrap all assets with our wrapper. The AssetSourceImpl class is responsible for providing IAsset instances to Tapestry. We'll extend this class and override the findAsset() method so that we can wrap the created assets with the wrapper class:

package myapp;

import java.util.Locale;

import org.apache.hivemind.Location;
import org.apache.hivemind.Resource;
import org.apache.tapestry.IAsset;
import org.apache.tapestry.asset.AssetSourceImpl;

public class BuildAwareAssetSourceImpl extends AssetSourceImpl {
    private AppProperties props;

    @Override
    public IAsset findAsset(Resource base, String path, Locale locale, Location location) {
        IAsset asset = super.findAsset(base, path, locale, location);
        return new BuildAwareAssetWrapper(asset, props.getBuild());
    }

    public void setAppProperties(AppProperties props) {
        this.props = props;
    }
}

注意,实现有一个二传手能接受我们的Spring bean。最后一步是让Tapestry的使用 BuildAwareAssetSourceImpl 以创建资产,而不是 AssetSourceImpl 。我们通过覆盖相应的服务点,做到这一点 hivemodule.xml

Notice that the implementation has a setter which can accept our Spring bean. The last step is to get Tapestry to use BuildAwareAssetSourceImpl to create assets instead of AssetSourceImpl. We do this by overriding the corresponding service point in hivemodule.xml:

<!-- Custom asset source -->
<implementation service-id="tapestry.asset.AssetSource">
    <invoke-factory service-id="hivemind.BuilderFactory" model="singleton">
        <construct class="myapp.BuildAwareAssetSourceImpl">
            <set-object property="appProperties" value="spring:appProperties"/>
            <set-configuration property="contributions" configuration-id="tapestry.asset.AssetFactories"/>
            <set-service property="lookupAssetFactory" service-id="tapestry.asset.LookupAssetFactory"/>
            <set-service property="defaultAssetFactory" service-id="tapestry.asset.DefaultAssetFactory"/>
        </construct>
    </invoke-factory>
</implementation>

就是这样。如果你运行应用程序并查看使用的资产的任何页面的源代码,你会看到URL上是否会有新的建立参数。

这篇关于挂毯4:资产高速缓存控制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆