URL динамического изображения калитки - PullRequest
6 голосов
/ 03 октября 2009

Короткий вопрос: Мне нужно превратить динамическое изображение, извлеченное из базы данных, в URL-адрес, не добавляя компонент на отображаемую страницу (например, используя NonCachingImage) с помощью Wicket.

Идеальное решение (которое я реализовал в других Frameworks) - просто создать страницу, которая использует идентификатор изображения в качестве параметра url и отображает изображение в потоке ответов. К сожалению, класс Page Wicket расширяет MarkupContainer, который вращается вокруг MarkupStreams. MarkupStreams не очень способствуют визуализации байтовых данных напрямую.

Длинный вопрос: Я использую Wicket 1.4.0, работающий в Tomcat 6.0.18. Изображение хранится в базе данных Postgres, полученной через JDBC. Изображение должно быть обработано сторонним API, который принимает только URL изображения. У меня есть объект модели, который содержит байтовые данные, тип MIME и объект Resource, который может извлечь модель из БД и добавить ее в поток ответов.

Есть идеи?

Ответы [ 3 ]

19 голосов
/ 03 октября 2009

Я только начал сам работать с 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 .

2 голосов
/ 19 января 2012

Я добавлю еще один ответ, чтобы сказать, что Мартин Григоров написал действительно хороший пост на wicketinaction.com, чтобы подробно рассказать о том, как обслуживать изображения, загруженные из базы данных в Wicket 1.5:

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

Это в точности соответствует вопросу @ Майкла.

1 голос
/ 03 октября 2009

Вот мой пример, который делает то же самое для динамически скомпилированного списка идентификаторов, который используется как общий ресурс со статическим 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);
    }
}

Извините, но я не могу найти учебник, который я использовал для его настройки, но должно быть очевидно, как это относится к приведенному выше примеру, и его можно настроить, чтобы сделать то же самое для изображений .. ( Извините за скудное объяснение, если еще неясно, я мог бы вернуться и отредактировать свой ответ)

...