从 Amazon S3 提供资源的惯用 Wicket 方式

Idiomatic Wicket way of serving resources from Amazon S3

从 AWS S3 提供用户上传资产的 Wicket 方式是什么?

要求:

我可以想到以下解决方案:

  1. 用于解析 URL 并流式传输资产的所有资源的单个 SharedResource:

    // resource definition:
    mountResources("/assets/${path}", new ResourceReference("assets") {
        public IResource getResource() {
            return new AbstractResource() {
                public ResourceResponse newResourceResponse(RequestAttribute attributes) {
                    String path = attributes.getParameters().get("path").toString()
                    // request S3 and stream the content
                    // handle caching / busting by hand
                } 
            }
        }
    })
    
    // Usage:
    page.add(new Image("image", new SharedResourceReference("assets"), new PageParameters().add("path", "image.jpg"))
    
  2. 为每个资产创建一个新的 ResourceReference 并将其直接传递给图像。通过让 Resource 实现 IStaticCacheableResource:

    来插入 Wicket 的缓存
    class S3ResourceReference extends ResourceReference {
        private String path;
        public S3ResourceReference(String path) { ... }
        public IResource getResource() {
            return new S3Resource(path);
        }
    }
    class S3Resource extends AbstractResource implements IStaticCacheableResource {
        public S3ResourceStream getResourceStream() {
            S3Object object = getObject(path);
            return new S3ResourceStream(object);
        }
        public ResourceResponse newResourceResponse(Attributes attributes) {
            S3ResourceStream stream = getResourceStream();
            // populate response
        }
    }
    
    class S3ResourceStream extends AbstractResourceStream {
        S3ResourceStream(S3Object object) {
            // ...
        }
    
        public InputStream getInputStream() { return object.objectContent }
        // override metadata methods
    }
    
    // Usage:
    page.add(new Image("image"), new S3ResourceReference("image.jpg"));
    

这些方法中哪种看起来更地道?

在第二个代码段中使用 IStaticCacheableResource 是否存在任何缺陷?

以下是这两种方法的区别:

页面实例锁定

  • 在 1) 中,对资源的请求是针对应用程序范围的资源
  • 在 2) 中,请求是针对页面范围的资源

在第二种情况下,Wicket 将在提供资源期间锁定对页面实例的访问。出于这个原因,我更喜欢使用应用程序范围的资源。

IStaticCacheableResource

如果资源实现此接口,则 Wicket 会将生成的 url 分解为资源,并在其文件名中添加类似 -123456789 的内容。这个散列是开发模式下的资源修改时间和生产模式下的 MD5 校验和。这有助于缓存。

我希望您意识到可以混合使用 1) 和 2) - 应用程序范围的资源引用 + IStaticCacheableResource。

还有一件事:我通常使用 new MyResourceReference() 而不是 new SharedResourceReference("the-name")