3

私は Tapestry 4 を使用していますが、アセット (画像、スタイル シート、JS ライブラリ) を変更するリリースをプッシュするたびに、ユーザーのブラウザー キャッシュに古いバージョンのアセットがまだ残っているため、問題が発生します。キャッシュを許可する簡単な方法を設定したいのですが、アプリケーションを更新するときに新しいアセットのダウンロードを強制します。資産のキャッシュを完全に禁止するだけでは、受け入れられる解決策ではありません。

これを行うための既存のメカニズムは見当たりませんでしたが、Tapestry にビルド番号を URL に追加するように指示する方法があるのではないかと考えていました。たとえば、次のようなものです。

http://www.test.com/path/to/the/asset/asset.jpg?12345

そうすれば、すべての新しいビルドが、エンド ユーザーにとって別のアセットのように見えます。

Tapestry は、私が気付いていないキャッシュの問題を解決する簡単な方法を提供しますか? そうでない場合、Tapestry によって生成された URL を変更するにはどうすればよいでしょうか? そして、それを行うコードはどのようにしてビルド番号を取得するのでしょうか? (たとえば、Spring Bean にビルド番号を入れることはできますが、新しい URL 構築メカニズムはどのようにそれを取得するのでしょうか?)

4

1 に答える 1

6

この問題について長い間煮詰めた後、私は最終的に自分で解決しました。このソリューションは、プロジェクトにタペストリ スプリング ライブラリがあることを前提としています。

私の場合、アプリケーションのグローバル プロパティの一部を含む Spring Bean があります。

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 を宣言します。

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

@BUILD_NUMBER@Ant ビルド スクリプトを設定して、実際の数値に置き換えることができます(詳細については、Ant マニュアルのコピータスクを参照してください)。

次に、 をラップIAssetしてビルド番号を 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;
    }
}

次に、すべてのアセットをラッパーでラップする Tapestry を作成する必要があります。このクラスは、Tapestry にインスタンスをAssetSourceImpl提供する責任があります。IAssetこのクラスを拡張してfindAsset()メソッドをオーバーライドし、作成したアセットをラッパー クラスでラップできるようにします。

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 を受け入れることができるセッターがあることに注意してください。最後のステップは、BuildAwareAssetSourceImplの代わりにタペストリーを使用してアセットを作成することですAssetSourceImpl。で対応するサービス ポイントをオーバーライドすることでこれを行います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 に新しいbuildパラメーターが含まれていることがわかります。

于 2009-02-25T05:39:02.650 に答える