2009-10-03 13 views
6

Krótkie pytanie: Potrzebuję włączyć dynamiczny obraz pobrany z bazy danych do adresu URL bez dodawania komponentu do strony wyświetlającej (np. Za pomocą NonCachingImage) za pomocą Wicket.Wicket Dynamic Image URL

Idealnym rozwiązaniem (które zaimplementowałem w innych frameworkach) jest po prostu utworzenie strony, która pobiera identyfikator obrazu jako parametr url i renderuje obraz do strumienia odpowiedzi. Niestety klasa strony Wicket rozszerza MarkupContainer, który obraca się wokół MarkupStreams. MarkupStreams nie sprzyja bezpośrednio renderowaniu danych bajtowych.

Długie pytanie: Używam Wicket 1.4.0, działa w Tomcat 6.0.18. Obraz jest przechowywany w bazie danych Postgres, pobranej przez JDBC. Obraz musi być renderowany przez zewnętrzny interfejs API akceptujący tylko adresy URL obrazów. Mam obiekt modelu, który zawiera dane bajtów, typ MIME i obiekt zasobu, który może pobrać model z bazy danych i dodać go do strumienia odpowiedzi.

Wszelkie pomysły?

Odpowiedz

19

Sam zacząłem pracować z Wicketem, ale po prostu zamontowałem zasób jako zasób udostępniony z własnym adresem URL. Wystarczy zastąpić init() w swoim Application i zarejestrować zasób

getSharedResources().add(resourceKey, dynamicImageResource); 

Następnie należy zamontować go jako zasobu udostępnionego z

mountSharedResource(path, resourceKey); 

z jakiegoś powodu, że wciąż nie w pełni zrozumieć, trzeba aby dodać nazwę klasy aplikacji do klucza zasobów, który przekazano do mountSharedResource().


Dodajmy w pełni działający przykład na niektóre bonusowe głosy! Najpierw utworzyć pusty szablon przejściowe bez

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

Następnie zastąpić metodę w WicketApplicationinit() dodając:

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

Mała dynamiczny zasób PNG właśnie pisze parametru zapytania na czarnym tle. Oczywiście, możesz uzyskać dostęp do bazy danych lub zrobić, co chcesz, aby uzyskać dane obrazu.

Na koniec wykonaj mvn jetty:run, aby uzyskać dostęp do zasobu pod numerem this URL.

+0

I uzupełnienie tego: Używanie klasy implementującej IInitializer i 'getSharedResources(). PutClassAlias ​​(ListInitializer.class," list "); new ListInitializer(). init (this); 'powinieneś być w stanie obejść, przygotowując całą ścieżkę classpath dla twojego adresu URL obrazu. – Tim

+0

Czy możesz podać więcej informacji, Tim? Nie mogę znaleźć klasy 'ListInitializer' w Wicket i dostępna dokumentacja na' putClassAlias' też nie jest przydatna. – janko

+0

ListInitializer to tylko moja implementacja. Rozwinę mój przykład na własną odpowiedź. – Tim

1

Oto mój przykład, że robi to samo dla dynamicznie sporządzoną listę identyfikatorów, służył jako zasobu udostępnionego ze statycznym adresem 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); 
    } 

i mój ListInitializer który rejestruje zasobów jak 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); 
    } 
} 

przykro mi, ale nie mogę wydawać się znaleźć samouczek Kiedyś Ustawiono już, ale powinno to być oczywiste, jak to odnosi się do powyższego przykładu i może być regulowana zrobić to samo dla obrazów .. (Przepraszam za nieliczne wyjaśnienie, jeśli ja t wciąż nie jest jasne, czy mógłbym wrócić i edytować odpowiedź)

+0

Otrzymano brak wyjaśnienia w dół głosowania .. czy należy się zastanowić? – Tim