代码之家  ›  专栏  ›  技术社区  ›  Robert J. Walker

Tapestry 4:资产缓存控制?

  •  3
  • Robert J. Walker  · 技术社区  · 16 年前

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

    这样,对于最终用户来说,每一个新构建都会使它看起来像一个不同的资产。

    Tapestry是否提供了一种简单的方法来解决我不知道的缓存问题?如果没有,我们将如何修改Tapestry生成的URL?负责这项工作的代码如何获得构建号?(例如,我可以将构建号输入到Springbean中,但新的URL构建机制如何实现这一点?)

    1 回复  |  直到 16 年前
        1
  •  6
  •   martin clayton egrunin    14 年前

    在对这个问题苦思冥想了很长时间后,我最终自己解决了它。此解决方案假定您具有 tapestry-spring library 在你的项目中。

    在我的例子中,我有一个Springbean,它包含我的应用程序的一些全局属性:

    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>
    

    您可以设置要替换的Ant构建脚本 @BUILD_NUMBER@ 实际数字(参见 Copy

    现在创建一个将包装的类 IAsset s并将内部版本号固定到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() 方法,以便使用包装器类包装创建的资产:

    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;
        }
    }
    

    注意,该实现有一个setter,可以接受我们的Springbean。最后一步是使用Tapestry BuildAwareAssetSourceImpl 资产来源 . 我们通过覆盖中相应的服务点来实现这一点 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 上面的参数。