Wie erstelle ich eine erweiterbare Webanwendung?

8

Wie würden Sie eine erweiterbare Webanwendung implementieren? Ich denke an eine Webanwendung ähnlich wie Jenkins oder Hudson, die Plug-In-Unterstützung bietet. Obwohl mir klar ist, wie Plug-Ins gefunden und geladen werden können, weiß ich nicht, wie sie in die Gesamtarchitektur integriert werden können. Über die folgenden Punkte bin ich besonders unsicher.

Wie kann ein Plug-In die Ansicht ändern, z. B. Eingabeelemente zu einem Formular hinzufügen?

Meine erste Idee wäre, dass ein Plug-In Partials / Fragmente für eine bestimmte Form registrieren kann.

Beispiel: Newsletter-Plug-In, das ein typisches Newsletter-Kontrollkästchenfragment registriert, das in der Benutzerregistrierungsansicht gerendert wird.

Wie kann ein Plug-In auf eingehende Anfragen reagieren?

Wiederum wäre ein direkter Ansatz, Listener für bestimmte Anforderungen oder Aktionen bereitzustellen, z. B. POST-Anforderung an / Benutzer.

Wie kann ein Plug-In Daten beibehalten?

Ich gehe davon aus, dass dies eine Situation ist, in der NoSQL-Datenspeicherlösungen relationalen Datenbanken überlegen wären.

Ich würde mich über Kommentare, Ideen und Erfahrungen (vielleicht gibt es sogar ein Designmuster) freuen, die Sie zu erweiterbaren Webanwendungen haben.

BenR
quelle

Antworten:

3

Ihre Frage enthält fast alle Antworten. Sie sind genau richtig: Es sind alles Plug-Ins und ihre Erweiterungspunkte, um den Kontext festzulegen und sie dazu zu bringen, die gewünschten Dinge zu tun. Es gibt verschiedene Möglichkeiten, Plug-In-Systeme zu entwerfen. Für Starter:

http://people.clarkson.edu/~dhou/courses/EE564-s07/plugin.pdf

http://blogs.atlassian.com/developer/2011/03/plugin_architecture_episode_i.html

Hier ist ein triviales Beispiel, um zu veranschaulichen, wie ein rudimentäres Plugin-fähiges System funktionieren würde:

public interface Plugin {

  void setEntityManager(EntityManager manager); // this is very course grained and liberal! A plugin would have access to whatever Entity Manager the container gives it. A plugin would then have a carte blanche to do whatever it needs: create, drop, insert, select, delete.

  View renderView(ViewContext context); // a plugin would render or return a view (whatever it is, could be a string in the simplest case) based on the context that the container passed to the plugin

  Action readEvent(Event event); // a plugin performs some Action based on an event as notified by a container

}


public class PluginContainer {

  private List<Plugin> plugins = new ArrayList<Plugin>();

  public void registerPlugins() {
    // loop through plugin descriptors obtained by your preferred mechanism
    // like introspecting libraries (JARs) in a configurable location

    // for each descriptor, load a Plugin dynamically and "register" it with a container
    Plugin p = ClassLoader.getSystemClassLoader().loadClass("com.my.PluginA").newInstance(); 
    p.setEntityManager(entityManager);
    plugins.add(p);
  }

  public void readEvent(AppEvent appEvent) {
    Event e = this.constructPluginSpecificEventFromAppEvent(); // optional
    for (Plugin p : this.plugins) {
      p.readEvent(e); // disregarding Action here
    }
  }
}

public class Application {

  private PluginContainer pContainer;

  private void buttonClicked(AppEvent appEvent) {
    this.showCoolDialog("Thank you for clicking a button!");
    // now let my plugins handle this
    // they can do whatever they want for this event
    // since they have access to EntityManager, they can work with a persistence storage as well
    this.pcContainer.readEvent(appEvent);
  }

}
Yuriy Zubarev
quelle