6

简短的问题:我需要将从数据库中提取的动态图像转换为 URL,而无需使用 Wicket 将组件添加到显示页面(例如使用 NonCachingImage)。

完美的解决方案(我已经在其他框架中实现)只是创建一个页面,该页面将图像 ID 作为 url 参数并将图像呈现给响应流。不幸的是,Wicket 的 Page 类扩展了 MarkupContainer,它围绕着 MarkupStreams。MarkupStreams 不太利于直接渲染字节数据。

长问题:我使用的是 Wicket 1.4.0,在 Tomcat 6.0.18 中运行。图像存储在 Postgres 数据库中,通过 JDBC 检索。图像需要由仅接受图像 URL 的第三方 API 呈现。我有一个模型对象,其中包含字节数据、mime 类型和一个资源对象,该对象可以从数据库中提取模型并将其添加到响应流中。

有任何想法吗?

4

3 回答 3

19

我自己才刚刚开始使用 Wicket,但我只是将资源作为共享资源挂载,并带有自己的 URL。init()您只需覆盖Application并注册资源

getSharedResources().add(resourceKey, dynamicImageResource);

然后,您将其挂载为共享资源

mountSharedResource(path, resourceKey);

出于某种原因,我仍然没有完全理解,您必须将应用程序的类名添加到您传递给的资源键中mountSharedResource()


让我们为一些奖金投票添加一个完整的示例!首先创建一个空的 Wicket 模板

mvn archetype:create -DarchetypeGroupId=org.apache.wicket \
    -DarchetypeArtifactId=wicket-archetype-quickstart \
    -DarchetypeVersion=1.4.0 -DgroupId=com.mycompany \
    -DartifactId=myproject

然后,通过添加覆盖该init()方法WicketApplication

@Override
protected void init() {
    final String resourceKey = "DYN_IMG_KEY";
    final String queryParm = "id";

    getSharedResources().add(resourceKey, new Resource() {
        @Override
        public IResourceStream getResourceStream() {
            final String query = getParameters().getString(queryParm);

            // generate an image containing the query argument
            final BufferedImage img = new BufferedImage(100, 100,
                    BufferedImage.TYPE_INT_RGB);
            final Graphics2D g2 = img.createGraphics();
            g2.setColor(Color.WHITE);
            g2.drawString(query, img.getWidth() / 2, img.getHeight() / 2);

            // return the image as a PNG stream
            return new AbstractResourceStreamWriter() {
                public String getContentType() {
                    return "image/png";
                }
                public void write(OutputStream output) {
                    try { ImageIO.write(img, "png", output); }
                    catch (IOException ex) { /* never swallow exceptions! */ }
                }
            };
        }
    });

    mountSharedResource("/resource", Application.class.getName() + "/" +
            resourceKey);
}

小动态PNG资源只是在黑色背景上写入查询参数。当然,您可以访问您的数据库或做任何您喜欢的事情来生成图像数据。

最后,执行mvn jetty:run,您将能够访问此 URL处的资源。

于 2009-10-03T09:52:05.993 回答
2

我将添加另一个答案,说 Martin Grigorov 在 wicketinaction.com 上写了一篇非常好的博文,详细介绍了如何提供从 Wicket 1.5 中的数据库加载的图像:

http://wicketinaction.com/2011/07/wicket-1-5-mounting-resources/

这与@Michael 的问题完全一致。

于 2012-01-19T08:04:36.680 回答
1

这是我的示例,它对动态编译的标识符列表执行相同的操作,作为具有静态 URL 的共享资源提供。

public class WicketApplication extends WebApplication {
    ...snip...
    @Override
    protected void init() {
        //Spring
        addComponentInstantiationListener(new SpringComponentInjector(this));

        //Register export lists as shared resources
        getSharedResources().putClassAlias(ListInitializer.class, "list");
        new ListInitializer().init(this);
    }

我的 ListInitializer 将资源注册为 DBNAME_SUBSELECTION1(2/3/..)

public class ListInitializer implements IInitializer {
    public ListInitializer() {
        InjectorHolder.getInjector().inject(this);
    }

    @SpringBean
    private DatabankDAO dbdao;

    @Override
    public void init(Application application) {
        //For each databank
        for (Databank db : dbdao.getAll()) {
            String dbname = db.getName();
            //and all collection types
            for (CollectionType ct : CollectionType.values()) {
                //create a resource
                Resource resource = getResource(dbname, ct);
                //and register it with shared resources
                application.getSharedResources().add(this.getClass(), dbname + '_' + ct, null, null, resource);
            }
        }
    }

    @SpringBean
    private MyApp   MyApp;

    public Resource getResource(final String db, final CollectionType collectionType) {
        return new WebResource() {
            @Override
            public IResourceStream getResourceStream() {
                List<String> entries = MyApp.getEntries(db, collectionType.toString());
                StringBuilder sb = new StringBuilder();
                for (String entry : entries) {
                    sb.append(entry.toString());
                    sb.append('\n');
                }
                return new StringResourceStream(sb, "text/plain");
            }

            @Override
            protected void setHeaders(WebResponse response) {
                super.setHeaders(response);
                response.setAttachmentHeader(db + '_' + collectionType);
            }
        }.setCacheable(false);
    }
}

很抱歉,我似乎再也找不到我用来设置它的教程了,但应该很明显这与上面的例子有什么关系,并且可以调整为对图像做同样的事情..(对不起稀疏的解释,如果仍然不清楚,我可以回来编辑我的答案)

于 2009-10-03T14:21:12.637 回答