Rob*_*ker 3 browser caching tapestry
我使用Tapestry 4,每当我们推出一个更改任何资产(图像,样式表,JS库)的版本时,我们就会遇到问题,因为用户的浏览器缓存中仍然有旧版本的资产.我想设置一些简单的方法来允许缓存,但在更新应用程序时强制下载新的资产.简单地完全不允许缓存资产是不可接受的解决方案.
我没有看到任何现有的机制,但我想到可能有一些方法告诉Tapestry将内部版本号添加到URL,如下所示:
http://www.test.com/path/to/the/asset/asset.jpg?12345
这样,每个新构建都会使它看起来像最终用户的不同资产.
Tapestry是否提供了一种解决我不知道的缓存问题的简单方法?如果没有,如何修改Tapestry生成的URL?负责这样做的代码如何获得内部版本号?(例如,我可以将构建号编入Spring bean,但是新的URL构建机制将如何获得它?)
在长时间咀嚼这个问题之后,我最终自己解决了这个问题.此解决方案假设您的项目中有tapestry-spring库.
在我的例子中,我有一个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
}
Run Code Online (Sandbox Code Playgroud)
在Spring配置中声明这个bean:
<bean id="appProperties" class="myapp.AppProperties">
<property name="build" value="@BUILD_NUMBER@"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
您可以设置Ant构建脚本以替换@BUILD_NUMBER@实际编号(有关详细信息,请参阅Ant手册中的" 复制"任务).
现在创建一个类来包装IAssets并将构建号添加到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;
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,我们需要使用我们的包装器使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;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,该实现有一个可以接受我们的Spring bean的setter.最后一步是让Tapestry 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>
Run Code Online (Sandbox Code Playgroud)
而已.如果您运行应用程序并查看使用资产的任何页面的源,您将看到该URL将包含新build参数.
| 归档时间: |
|
| 查看次数: |
1303 次 |
| 最近记录: |