IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

10. diel - Java server - Systém pluginov

V minulej lekcii, Java server - Event bus , sme sa venovali propagáciu udalostí naprieč serverom pomocou event bus. Dnes navrhneme a implementujeme systém, pomocou ktorého budeme môcť ľahko rozširovať funkcionalitu servera.

Plugin

Na úvod by bolo dobré zadefinovať, čo to plugin vlastne je. Plugin bude predstavovať jednotlivé funkcionality servera. Pod termínom funkcionalita servera si môžete predstaviť:

  • správa užívateľov
  • prístup k databáze
  • chat
  • komunikácia s externou službou
  • a ďalšie ...

Návrh systému pluginov

Náš pluginový systém bude relatívne jednoduchý. Bude mať za úlohu pri štarte servera načítať všetky dostupné pluginy a inicializovať je. V budúcnosti doplníme tento systém o načítanie pluginov z externých jar súborov, aby sme nemuseli server překompilovat zakaždým, keď bude niekto chcieť pridať novú funkciu.

Implementácia

Implementáciu začneme návrhom rozhranie, ktoré bude reprezentovať plugin. Rozhranie nazveme IPlugin a vložíme ho do samostatného balíčka plugins. Rozhranie bude pre začiatok obsahovať metódu getName(), ktorá ako už názov napovedá vráti názov pluginu. Ďalej metódu init(), v ktorej sa bude plugin inicializovať. Pomocou metódy registerMessageHandlers() bude môcť plugin zaregistrovať všetky udalosti, na ktoré bude v budúcnosti reagovať. V metóde setupDependencies() bude možné prepojiť jednotlivé doplnky dohromady. Celé rozhranie vyzerá nasledovne:

package cz.stechy.chat.plugins;

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

V rovnakom balíčku vytvoríme zoznam, ktorý bude obsahovať všetky pluginy, ktoré budú zakomponované priamo v servera. Výpočet nazvime jednoducho Plugin. Výpočet bude obsahovať konštantu typu Class<? extends IPlugin>. Nezabudnite na konštruktor:

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

Táto konštanta bude odkazovať na triedu, ktorá implementuje plugin. Pre zatiaľ je výpočet prázdny, preto musí byť na začiatku prítomný bodkočiarku.

Teraz zaregistrujeme všetky moduly do Google Guice, aby nám ich automaticky instancioval. Vytvoríme nový modul PluginModule, ktorý bude dediť z triedy AbstractModule, ktorú nám poskytuje knižnica Guice a implementujeme metódu 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 tejto metóde si pripravíme premennú pluginBinder, pomocou ktorej škárujeme implementácie všetkých pluginov s naším rozhraním IPlugin. Viac o implementácii MapBinderu nájdete na wiki Guice. Spárovanie vykonáme v slučke, v ktorej budeme iterovat cez zoznam pluginov, ktoré sú priamo na serveri. Za zmienku už stojí len volanie metódy asEagerSingleton(), ktorá hovorí, že kedykoľvek zažiadame o konkrétnu inštanciu pluginu, zakaždým dostaneme tú istú. Načítanie externých pluginov si necháme na neskôr.

Ďalej zaregistrujeme novovytvorený modul do Guice. V triede Server, v metóde main(), kde sa vytvára inštancie triedy Injector, pridáme nový modul PluginModul:

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

Nakoniec upravíme triedu Server. Pridáme konštantu typu Map<String, IPlugin> a konštantu typu IEventBus. Tieto konštanty bude trieda prijímať 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;
}

Teraz už zostáva postarať sa o inicializáciu pluginov. Na tento účel si vytvoríme privátne metódu initPlugins(), v ktorej sa postaráme o inicializácii:

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

Najskôr zavoláme nad všetkými pluginy metódu init() a dáme im možnosť sa inicializovať. Ďalej prejdeme do fázy registrácie poslucháčov na príslušné udalosti a nakoniec necháme pluginy, aby si nastavili svojej závislosti medzi sebou. Metódu initPlugins() budeme volať pred štartom vlákna servera.

Použitie

Pre demonštračné účely vytvoríme jednoduchý plugin, ktorý nebude robiť nič, iba vo fáze inicializácia vypíše svoj názov do konzoly. V balíčku plugins vytvoríme ďalší balíček s názvom hello. V tomto balíčku vytvoríme triedu HelloPlugin, ktorá bude implementovať naše rozhranie IPlugin. Požadované metódy implementujeme nasledovne:

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 pridáme do zoznamu pluginov. Nezabudnite, že nestačí pridať iba názov, ale i triedu, ktorá implementuje daný plugin:

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

To je všetko. Keď spustíte server, dostanete hlášku, že sa plugin Inicializoval.

To by bolo z dnešnej lekcie všetko. V budúcej lekcii, Java server - Propagácia lokálnou sieťou (1. časť) , pripravíme základ pre zviditeľnenie servera v lokálnej sieti.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 22x (288.88 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Java server - Event bus
Všetky články v sekcii
Server pre klientskej aplikácie v Jave
Preskočiť článok
(neodporúčame)
Java server - Propagácia lokálnou sieťou (1. časť)
Článok pre vás napísal Petr Štechmüller
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje primárně programování v Javě, ale nebojí se ani webových technologií.
Aktivity