Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 10 - Java server - Systém pluginů

V minulé lekci, Java server - Event bus, jsme se věnovali propagaci událostí napříč serverem pomocí event bus.

Dnes navrhneme a implementujeme systém, pomocí kterého budeme moci snadno rozšiřovat funkcionalitu serveru.

Plugin

Na úvod by bylo dobré zadefinovat, co to plugin vlastně je. Plugin bude představovat jednotlivé funkcionality serveru. Pod termínem funkcionalita serveru si můžete představit:

  • správa uživatelů
  • přístup k databázi
  • chat
  • komunikace s externí službou
  • a další...

Návrh systému pluginů

Náš pluginový systém bude relativně jednoduchý. Bude mít za úkol při startu serveru načíst všechny dostupné pluginy a inicializovat je. V budoucnu doplníme tento systém o načítání pluginů z externích jar souborů, abychom nemuseli server překompilovat pokaždé, když bude někdo chtít přidat novou funkci.

Implementace

Implementaci začneme návrhem rozhraní, které bude reprezentovat plugin. Rozhraní nazveme IPlugin a vložíme ho do samostatného balíčku plugins. Rozhraní bude pro začátek obsahovat metodu getName(), která jak již název napovídá vrátí název pluginu. Dále metodu init(), ve které se bude plugin inicializovat. Pomocí metody registerMessageHandlers() bude moci plugin zaregistrovat všechny události, na které bude v budoucnu reagovat. V metodě setupDependencies() bude možné propojit jednotlivé pluginy dohromady. Celé rozhraní vypadá následovně:

package cz.stechy.chat.plugins;

public interface IPlugin {
    String getName();
    void init();
    void registerMessageHandlers(IEventBus eventBus);
    void setupDependencies(Map<String, IPlugin> otherPlugins);
}

Ve stejném balíčku vytvoříme výčet, který bude obsahovat veškeré pluginy, které budou zakomponovány přímo v serveru. Výčet nazvěme jednoduše Plugin. Výčet bude obsahovat konstantu typu Class<? extends IPlugin>. Nezapomeňte na konstruktor:

public enum Plugin {
    ;
    public final Class<? extends IPlugin> clazz;
    Plugin(Class<? extends IPlugin> clazz) {
        this.clazz = clazz;
    }
}

Tato konstanta bude odkazovat na třídu, která implementuje plugin. Prozatím je výčet prázdný, proto musí být na začátku přítomen středník.

Nyní zaregistrujeme všechny moduly do Google guice, aby nám je automaticky instancioval. Vytvoříme nový modul PluginModule, který bude dědit ze třídy AbstractModule, kterou nám poskytuje knihovna guice a implementujeme metodu configure:

public class PluginModule extends AbstractModule {

    @Override
    protected void configure() {
        MapBinder < String, IPlugin > pluginBinder = MapBinder.newMapBinder(binder(), String.class, IPlugin.class);
        for (Plugin plugin: Plugin.values()) {
            pluginBinder.addBinding(plugin.name()).to(plugin.clazz).asEagerSingleton();
        }

        // TODO načíst externí pluginy
    }
}

V této metodě si připravíme proměnnou pluginBinder, pomocí které spárujeme implementace všech pluginů s naším rozhraním IPlugin. Více o implementaci MapBinder najdete na wiki guice. Spárování provedeme ve smyčce, ve které budeme iterovat přes výčet pluginů, které jsou přímo na serveru. Za zmínku už stojí jen volání metody asEagerSingleton(), která říká, že kdykoliv zažádáme o konkrétní instanci pluginu, pokaždé dostaneme tu samou. Načtení externích pluginů si necháme na později.

Dále zaregistrujeme nově vytvořený modul do guice. Ve třídě Server, v metodě main(), kde se vytváří instance třídy Injector, přidáme nový modul PluginModul:

final Injector injector = Guice.createInjector(new ServerModule(), new PluginModule());

Nakonec upravíme třídu Server. Přidáme konstantu typu Map<String, IPlugin> a konstantu typu IEventBus. Tyto konstanty bude třída přijímat v konstruktoru:

@Inject
public Server(IParameterFactory parameterFactory, IServerThreadFactory serverThreadFactory,
    IEventBus eventBus, Map<String, IPlugin> plugins) {
    this.parameterFactory = parameterFactory;
    this.serverThreadFactory = serverThreadFactory;
    this.eventBus = eventBus;
    this.plugins = plugins;
}

Nyní již zbývá postarat se o inicializaci pluginů. Za tímto účelem si vytvoříme privátní metodu initPlugins(), ve které se postaráme o inicializaci:

private void initPlugins() {
    for (IPlugin plugin: plugins.values()) {
        plugin.init();
    }
    for (IPlugin plugin: plugins.values()) {
        plugin.registerMessageHandlers(messageRegistrator);
    }
    for (IPlugin plugin: plugins.values()) {
        plugin.setupDependencies(plugins);
    }
}

Nejdříve zavoláme nad všemi pluginy metodu init() a dáme jim možnost se inicializovat. Dále přejdeme do fáze registrace posluchačů na příslušné události a nakonec necháme pluginy, aby si nastavily své závislosti mezi sebou. Metodu initPlugins() budeme volat před startem vlákna serveru.

Použití

Pro demonstrační účely vytvoříme jednoduchý plugin, který nebude dělat nic, pouze ve fázi inicializace vypíše svůj název do konzole. V balíčku plugins vytvoříme další balíček s názvem hello. V tomto balíčku vytvoříme třídu HelloPlugin, která bude implementovat naše rozhraní IPlugin. Požadované metody implementujeme následovně:

package cz.stechy.chat.plugins.hello;

public class HelloPlugin implements IPlugin {

    @Override
    public String getName() {
        return "HelloPlugin";
    }

    @Override
    public void init() {
        System.out.println("Inicializace pluginu: " + getName());
    }
}

Záznam o pluginu přidáme do výčtu pluginů. Nezapomeňte, že nestačí přidat pouze název, ale i třídu, která implementuje daný plugin:

public enum Plugin {
    HELLO(HelloPlugin.class);
    ...
}

To je vše. Když spustíte server, dostanete hlášku, že se plugin inicializoval.

To by bylo z dnešní lekce vše.

V následujícím kvízu, Kvíz - Komunikační protokol, Event bus a pluginy v Javě, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 21x (288.88 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Java server - Event bus
Všechny články v sekci
Server pro klientské aplikace v Javě
Přeskočit článek
(nedoporučujeme)
Kvíz - Komunikační protokol, Event bus a pluginy v Javě
Článek pro vás napsal Petr Štechmüller
Avatar
Uživatelské hodnocení:
1 hlasů
Autor se věnuje primárně programování v Javě, ale nebojí se ani webových technologií.
Aktivity