2009-10-03 10 views
6

Courte question: Je dois transformer une image dynamique tirée d'une base de données en une URL sans ajouter un composant à la page d'affichage (comme en utilisant un NonCachingImage) en utilisant Wicket.Wicket Dynamic Image URL

La solution parfaite (que j'ai implémentée dans d'autres Frameworks) est simplement de créer une page qui prend l'image ID comme paramètre url et restitue l'image au flux de réponse. Malheureusement, la classe Page de Wicket étend MarkupContainer, qui tourne autour de MarkupStreams. MarkupStreams ne sont pas très propices au rendu des données d'octets directement. J'utilise Wicket 1.4.0, s'exécutant dans Tomcat 6.0.18. L'image est stockée dans une base de données Postgres, récupérée via JDBC. L'image doit être rendue par une API tierce qui n'accepte que les URL d'image. J'ai un objet modèle qui contient les données d'octet, le type MIME et un objet Ressource qui peut extraire le modèle de la base de données et l'ajouter à un flux de réponse.

Des idées?

Répondre

19

Je viens juste de commencer à travailler avec Wicket moi-même, mais je voudrais simplement monter la ressource en tant que ressource partagée avec sa propre URL. Vous venez de passer outre init() dans votre Application et enregistrez la ressource avec

getSharedResources().add(resourceKey, dynamicImageResource); 

Ensuite, vous montez comme une ressource partagée avec

mountSharedResource(path, resourceKey); 

Pour une raison quelconque, que je ne saisis pas tout à fait encore, vous avez pour préfixer le nom de classe de l'application à la clé de ressource que vous transmettez à mountSharedResource().


Ajoutons un exemple complet pour certains votes bonus! Tout d'abord créer un modèle de Wicket vide avec

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

Ensuite, remplacer la méthode init() dans WicketApplication en ajoutant:

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

La petite ressource PNG dynamique écrit simplement le paramètre de requête sur fond noir. Bien sûr, vous pouvez accéder à votre base de données ou faire ce que vous voulez pour produire les données d'image.

Enfin, exécutez mvn jetty:run et vous pourrez accéder à la ressource au this URL.

+0

Et pour compléter ceci: En utilisant une classe d'implémentation IInitializer et 'getSharedResources(). PutClassAlias ​​(ListInitializer.class," list "); new ListInitializer() .init (this); 'vous devriez pouvoir contourner le chemin de classe entier pour votre URL d'image. – Tim

+0

Pouvez-vous fournir plus d'informations, Tim? Je ne trouve pas la classe 'ListInitializer' dans Wicket et la documentation disponible sur' putClassAlias' n'est pas utile non plus. – janko

+0

ListInitializer est juste ma mise en œuvre .. Je vais développer mon exemple dans une réponse propre .. – Tim

1

Voici mon exemple qui fait la même chose pour une liste compilée dynamiquement des identifiants, servi comme une ressource partagée avec une URL statique ..

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

Et mon ListInitializer qui enregistre les ressources comme 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); 
    } 
} 

Je suis désolé mais je ne peux pas sembler trouver le tutoriel je configurer cela plus, mais il devrait être évident comment cela se rapporte à l'exemple ci-dessus et peut être ajustée faire la même chose pour les images .. (Désolé pour l'explication clairsemée, si je Je ne peux pas encore dire que je pourrais revenir et éditer ma réponse)

+0

A reçu une explication sans vote ... attention à élaborer? – Tim