Vánoční nadílka Vánoční nadílka
Vánoční akce! Daruj lepší budoucnost blízkým nebo sobě. Až +50 % zdarma na dárkové poukazy. Více informací

Lekce 10 - Java server - Systém pluginů

Java Server pro klientské aplikace Java server - Systém pluginů

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

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. Pro zatí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 MapBinderu 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 příští lekci, Java server - Propagace lokální sítí (1. část), připravíme základ pro zviditelnění serveru v lokální síti.


 

Stáhnout

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

 

 

Článek pro vás napsal Petr Štechmüller
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje primárně programování v Jave, ale nebojí se ani webových technologií.
Aktivity (2)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!