Java szervletek

Bevezetés

A Web gyors átalakuláson ment keresztül, egyszerű közlési eszközből kifinomult alkalmazási környezetté vált. A Web tartalmának egyre nagyobb része statikus HTML fájlok hleyett dinamikusan generált lapokba került, melyek egyszeri megjelenés után eltűnnek. Sokan a webhelyek közül, különösen a nagyobb kiskereskedelmi helyek, melyeknek állandóan változó raktárakkal és árakkal kell dolgozniuk, teljes egészében dinamikusan generált lapokból állnak, egyetlen HTML fájlt sem tartalmaznak.

A dinamikusan generált tartalomnak sok előnye van: elmarad a HTML fájlok verzióellenőrzése, a lapok jobban elviselik a változó környezetet, a tartalmat minden olvasónál testre lehet szabni. Van azonban egy hátrány. A dinamikusan generált webhelyek sokkal több kifinomult programzási munkát kívánnak a tartalmuk megalkotásánál és átadásánál. Az új Java Servlet API  és a Web szerverek segítséget nyújtnak azáltal, hogy  könnyen kezelhető, nagyteljesítmlnyű, rugalmas Java platformot adnak a weblapok röptében való összeállításához.

Java web server platform

A java platform végfelhasználói alkalmazásokban és elosztott alkalmazások kliens oldalán tapasztalt népszerűségének több oka van. A java nyelv a fáradságosabb programozói feladatok közül, mint például a memóriakezelés, sokat automatikusan elvégez. Hagyja a programozót, hogy a tényleges alkalmazásra összpontosítson, a jelentéktelen nyelvi részletkérdések helyett. A java alaposztályok sok hasznos adatmanipulációs és tárolási osztályt foglalnak magukba, amelyek még kevesebb alkalmazástól független kódot kívánnak meg a programozótól. Végül az írd meg egyszer, futtasd bárhol zárja le a minden lehetséges klienst támogatni akaró átültetési erőfeszítések sorát.

A szerveroldali alkalmazásfejlesztők is részesülnek ezekben az előnyökben. Ezenkívül, mivel a szerveroldali programozóknak gyakran kell foglalkozniuk a fájlrendszerek és operációs rendszer-specifikus struktúrák részleteivel, mint például konfigurációs fájlok és portszámok, a java platformon szerveroldali alkalmazások egy kis odafigyeléssel és előrelátással szintén bárhol futtathatóra írhatók.  A közbenső réteg alkatelemei gyakran éppen olyan platformfüggetlenné tehetők, mint a kliensoldali appletek.

A java szervletek

A szervletek Java nyelven készült olyan szerveroldali szoftverkomponensek, amelyek Java-futtató rendszerrel elátott HTTP szerverekbe beágyazva kliensek részére különféle szolgáltatásokat nyújthatnak.[4]   Tehát a szervlet valójában egy speciális Java program, amely egy webszerverrel szorosan együttműködve a szerveroldalon lehetővé teszi HTML oldalak dinamikus létrehozását és paraméterezését különböző átviteli (például HTTP) protokollon keresztül.[5] Mivel ezek a programok a szerver oldalán működnek, ezért a kliensek felé nyújtott szolgáltatásuknak nem része a felhasználói felület biztosítása.[4] Pontosabban a webszerver funkcionalitását lehet velük kibővíteni, mert ha egy kliens olyan HTML oldalt kér a webszervertől, melyet egy szervlet állít elő, akkor a webszerver tulajdonképp csak delegálja a kérést a szervlet felé, majd a szervlet által generált oldalt továbbítja a kliensnek. [5]

Bár a szervletek Java nyelven készülnek, a szolgáltatásaikat természetesen bármilyen operációs rendszeren működő, bármilyen programozási nyelven elkészített programokból igénybe lehet venni.  A lényeg az, hogy a szolgáltatásokat igénybe venni szándékozó alkalmazás valahogyan képes legyen a hálózaton keresztül történő kommunikációra. Természetesen a szervletek nemcsak szerver szerepköröket tölthetnek be, például az említett három résztvevős kliens-szerver struktúrában a szervletek a középső, alkalmazásfüggő szerver komponensek szerepét is betölthetik úgy, hogy közben maguk is kliensei valamely háttéradatbázis elérését biztosító szervernek.

A szervletek sokféle célra használhatók. A tipikus felhasználási céljaik között említést érdemel a HTML-űrlapok feldolgozása és a háttérben lévő JDBC programozói felülettel elérhető adatbázisok karbantartása az űrlapok tartalma alapján. Ezenkívül a szervletek jól felhasználhatók több résztvevő szinkronizált kommunikációjának megszervezésére is olyan alkalmazásstruktúrában, ahol egy több kliens párhuzamos kiszolgálását végző szervlet alkalmazás az összes rákapcsolódott kliens szinkronizált kommunikációjának megvalósításában segíthet. A szervletek képesek a kliens alkalmazások kéréseinek más szerveroldali komponensekhez történő továbbítására, így a szervletek részt vehetnek középső, alkalmazásfüggő szerver komponensként a háttérben levő szerverek terheléskiegyenlítését segítő stratégiák megvalósításában.

Szervlet Fejlesztőkörnyezet

A webszerver és a szervlet  közti kommunikáció a szervlet API-n keresztül történik. Szervleteket tehát csakis olyan webszerverekkel lehet használni, melyek támogatják ezen API-t, és természetesen képesek Java programok futtatására. A servlet API nem része a standard JDK-nak, de letölthető hozzá különálló fejlesztőkörnyezet (JSDK- Java Servlet Development Kit). A fejlsztőkörnyezet tartalmazza a szervlet API implementációját, HTML dokumentációját, néhány példaprogramot, valamint egy egyszerű Java alapú webszervert, melynek segítségével akkor is kipróbálhatjuk szervleteinket, ha nincs a gépünkön más webszerver telepítve.

Fordítás

A szervlet API implementációját a servlet.jar fájl tartalmazza. Szervlet fordításakor ezen fájlnak elérhetőnek kell lennie az osztályelérési útvonalon keresztül. A lefordított szervlet bájtkódját a webszerver előre megadott alkönyvtárába kell másolni. Ennek pontos elhelyezkedése a webszerver konfigurációjától függ, de rendszerint egy servlets nevű alkönyvtárat szoktak használni erre a célra.

Futtatás

Mivel egy szervlet csak egy webszerverrel együtt képes működni, ezért a szervlet futtatása a webszerver feladata. Erre akkor kerül sor, ha a webszerver olyan kérést kapott, melyet a szervletnek kell feldolgoznia. Ez rendszerint a kért url alapján könnyen megállapítható, mert az a szervleteket tartalmazó útvonalat (általában /servlet), valamint a futtatandó szervlet nevét tartalmazza. Ilyenkor a kért szervlet szolgálja ki a kliens kérését, a webszerver pedig a szervlet válaszát adja vissza html oldalként. Tehát a kliensoldal legfeljebb a kért url alapján jöhet rá, hogy egy szervlettől kapott választ, mivel a kliens szemszögéből semmi más különbség nincs egy statikus html oldal, illetve egy szervletet megadó url lehívása között.

A Szervletek Előnyei

A világháló első legnagyobb újításainak egyike a common gateaway interface (cgi) volt. A cgi előtt a web statikus kőzeg volt, az információt mozdulatlan szövegoldalak, és képek formájában továbbította. A cgi a webmestereket képessé tette arra, hogy dinamikusan generálják a html lapokat. Nemcsak a web tartalmát lehetett a felhasználó igényeire szabni, a felhasználó vissza is küldhetett információt a http szervernek. Ez a kétirányú adatforgalom a web-et egyszerű publikációs eszközből az elektronikus kereskedelem, intranet alkalmazások és más tranzakciós eszközök felületévé tette.

A.)Teljesítmény

A szervletek használata 30-szor gyorsabb lehet, mint a cgi. A szervletek nyitott java api-t képviselnek és sok http szerver támogatja őket. Ez kiterjeszti az alapvető írd meg egyszer, futtasd bárhol elvet a web backend oldalára is.

Gyakorlatilag egy szervlet nagyon hasonló módon működik, mint egy cgi lapgenerátor. A szervlet egy java osztály, mely egy webszerverbe töltődik és, a hoszt webszerveréhez intézett http kérésre felhasználva helyi adatokat, a kérést adó böngésző által átadott paramétereket és egyéb erőforrásokat, html lapot vagy más felismerhető típusú választ készít és visszaadja ezt a szervernek. Mivel a szervlet ugyanabban a processzben és címtérben fut, mint az ő hoszt webszervere, nagyon kicsi a szervlethívással kapcsolatos processzek közti adminisztrációs munka (overhead). A http szerver egyszerűen egy külön szálban meghívja a szervletet és továbbítja az eredményeket a kérést adó webböngészőnek. Ez sokkal gyorsabb, mint a tipikus cgi fork/exec/takarítás műveletsor.

B.) Egyszerű használat

A szervleteknél a paramétereket a szervletnek előre elemzett hash-táblákban adják át. E hash-táblák segítségével könnyű a hozzáférés a felhasználói adatokhoz.

C.) Biztonság

Mivel a szervleteket a belső szerkezeténél fogva biztonságosabb java nyelven írják, sokkal kevesbé valószínű, hogy a http helyi biztonsága elleni támadások sikerülnek. Olyan webszerverek, melyek szervleteket és java 2-t implementálnak, védelmi tartományokat használhatnak alkalmazástól függő biztonsági intézkedések implementálásához. 

Szervletek installálása egy webszerverre

A szervletet egy olyan szerverre kell felinstallálni, amelyik kommunikálni tud a szervletekkel.

Általában három forrásból tölthetők fel:

·                     classpath-ból

·                     a servlets könyvtárból

·                     egy URL-ről

Szervlet Tartós Telepítése

A szervlet tartós telepítése két dolgot követel meg: a szervlet betöltését amikor a webszervert indítjuk, csökkentve a várakozási időt, és a szervlethez egy álnév rendelését. Ez lehetővé teszi, hogy második nevet adjunk a szervletnek, lehetőleg egy .html kiterjesztéssel ellátott nevet.  Ez elrejti a tényt, hogy egy url egy szabályos html lap helyett egy szervletre mutat. Ennél fontosabb, hogy el tudjuk rejteni a szervletet implementáló osztályok nevét.  Ha egy bizonyos idő után kicserélnénk az implementáló osztályt az összes kereszthivatkozások és könyvjelzők aktualizálása gondot okozna, amit a legtöbben szeretnénk elkerülni. Az implementációs osztályokat egy álnév mögé rejtve kitérhetünk e probléma elől.

Felhasználói input

A dinamikus lapgenerálás egyik legáltalánosabb felhasználása a HTML formákból kapott input adatok feldolgozása. Ilyenkor szövegmezőkből, legörgethető menükből és egyéb GUI elemekből álló egyszerű formákat használunk a felhasználótól kapott adatok begyűjtésére. Ezek az adatok ezután egy HTTP GET vagy POST kérésben vonódnak össze, amely a webszerveren a megfelelő programot meghívja. A program ezt az inputot az adatbázis lekérdezések, fájl-pásztázások, árumegrendelések kialakítására, vagy más tevékenységekre használja. A program visszaadja a kért adatokat vagy annak megerősítését, hogy a megrendelés egy HTML lapra került.

A szervlet API ezt a fajta felhasználói interakciót azzal könnyíti meg, hogy egyszerű mechanizmust ad HTML formákból kapott input vételére és elemzésére.

A Java szervletek szerkezete

Általános dolgok

A javax.servlet csomag tartalmazza az összes szervletspecifikus osztályt és interfészt. Minden szervlet vagy a javax.servlet.GenericServlet leszármazottja vagy maga implementálja a javax.servlet.Servlet interfészt, amely az általános szervlet életciklus metódusokat specifikálja.[5]   Ez az interfész nevezi meg azokat a metódusokat, amelyeket minden szervletnek meg kell valósítania.

A Java szervletek működése: fogadják a kliensektől származó kéréseket, elvégzik a kliensek által kívánt szolgáltatásokat, és a kliensnek különféle adatokat küldenek vissza. Nem szabványos bementről kapják a kliensek kéréseiből származó adatokat, illetve nem a szabványos kimenetükre írják a válaszukat. A szervlet szolgáltatását megvalósító metódus a paraméterében kapott adatok alapján tud egy-egy bemeneti, illetve kimeneti Java I/O csatornát létrehozni, amin keresztül a klienstől érkezett adatokhoz hozzájuthat, illetve amin keresztül a kliensének válaszolhat.

public interface Servlet{

   public void init(ServletConfig config) throws ServletException;

   public ServletConfig getServletConfig();

   public void service(ServletRequest kérés, ServletResponse válasz)

    throws ServletException, IOException;

   public String getServletInfo();

   public void destroy();

}

A javax.servlet.Servlet interfész egy szervlet életének legfontosabb metódusait definiálja. A szervlet életciklusa alatt a következő három eseményt értjük:

·                     szervlet példányosítása  

·                     szervlet kiszolgál egy kliens kérést 

·                     szervlet megszüntetése.

Ezen eseményekhez tartozó metódusokat a szervlet interfész specifikálja és a webszerver hívja meg.

a.) Init metódus       

Az init() metódust a servletet betöltő szerver hívja meg a szervletet implementáló osztály példányosításakor. Erre vonatkozóan talán a legfontosabb tudnivaló, hogy amíg ez a metódus nem fut le, addig a szervlet szolgáltatásait implementáló service() metódus nem kerül végrehajtásra.  Az init() metódus paraméterében egy javax.servlet.ServletConfig interfészt implementáló objektumot kap, ami információkat tartalmaz egy szervlet futási környezetéről. Ezzel lehetőség nyílik önálló szervlet példányok létrehozására ugyanannak a szervlet osztálynak más kezdeti paraméterezésével (a különbözőképpen felparaméterezett szervletek a klienseik felé különböző szolgáltatásokat is nyújthatnak). Az init() metódusnak a paraméterében kapott objektumot el kell tárolnia, és szükség esetén az objektum getServletConfig() metódusának meghívásakor az eltárolt objektumpéldányt a hívónak vissza kell adnia. A paraméterek a ServletConfig objektum getInitParameter metódusa által hozzáférhetők. A getParameterValues-hez hasonlóan a getInitParameters egy String-et kap paraméterként, mely a kívánt paraméter nevét tartalmazza. Eltérően a getParameterValues-től, a getInitParameters egy String-et ad vissza String-tömb helyett. Ennek oka az, hogy egy init paraméternek csak egy értéke van: egy String érték.  Amennyiben az init() metódus nem tudta a kívánt szervletet inicializálni (mert például az elinduláshoz szükséges adatokat tároló valamelyik adatbázis szerver nem elérhető), akkor egy javax.servlet.UnavailableException kivételt kell generálnia, ez a kivétel kellő információt nyújthat a szervletet indítani szándékozó szerverprogramnak a hiba jellegéről, illetve arról, hogy érdemes-e a szervlet elindítását újból megpróbálni.

b.) Szervlet beanek

A szervlet beaneknek két nagy előnye van az init tulajdonságokkal szemben. Az egyik az, hogy míg az init tulajdonságok csak a szervlet inicializálása alatt állíthatóak be, a bean tulajdonságok bármikor. Eszerint a bean tulajdonságai röptében, futás közben módosíthatóak. Nem kell kiűríteni és újra betölteni a szervletet, vagy a webszervert újraindítani ahhoz, hogy a tulajdonságokat újraolvassa. A másik nagy előny az, hogy az összes Java Beanhez hasonlóan a szervlet beanek önleírók

c.) A service() metódus

A szervletek fontosabb metódusaihoz tartozik a service() metódus. Egy szervlet service() metódusa implementálja a kliensek felé nyújtott szolgáltatást, ennek a metódusnak a feladata egy kliens kiszolgálása. Egy szervlet service() metódusának hívásai nem lesznek szinkronizálva, így ha egyszerre több kliens is igénybe kívánja venni egy szervlet szolgáltatását, akkor az illető szervlet service() metódusa egyidejűleg több egymástól független végrehajtási szálon is aktív lehet. Ilyenkor a végrehajtási szálak közösen használt erőforrásaihoz való hozzáférés szinkronizációjáról a szervlet készítőjének kell gondoskodnia. A service() metódus első paraméterében megkap egy javax.servlet.ServletRequest interfészt implementáló objektumot, ami a kliens kéréséről tárol információkat, a második paraméterében kapott javax.servlet.ServletResponse interfészt implementáló objektum segítségével pedig a kliensnek küldhetők vissza a válaszadatok.  A szervlet a szokásos static módosítóval ellátott osztályváltozóiban tárolhat például állapot információkat a párhuzamosan (vagy egymás után) kiszolgált kliensekkel felépített kapcsolatairól, így szükség esetén az egyes kliens/szerver kapcsolatok egymás közti adatcseréje ezúton megoldható.

d.) A destroy() metódus

A destroy() metódust a szervlet futtató környezete akkor hívja meg, ha a szervlet szolgáltatásaira a közeljövőben várhatóan nem lesz szükség. A szervlet futtató környezete ezt a metódust meghívhatja például olyankor, ha az illető szervlet szolgáltatásait már régóta nem vették igénybe, de akkor is, ha a rendszergazda erre utasította. Amíg egy szervletpéldány klienseket szolgál ki, addig ez a metódusa nem lesz meghívva. Egy kliens kiszolgálása e tekintetben a service() metódus futásának idejéig tart, így ha e metódus úgy működik, hogy egy új önálló programszálat indít a kliens kiszolgálására, és a metódus még azelőtt visszaér, mielőtt ez az elindított programszál befejezné a tevékenységét, akkor a szervletet készítő programozónak kell gondoskodnia az illető programszálak megfelelő befejezéséről. A destroy() metódus feladatai közé tartozik a szervlet által a futása során lefoglalt erőforrások felszabadítása, illetve a szervlet későbbi újraindításához esetleg szükséges adatok kimentése.

Szervletek inicializációja

Az előzőekben már láthattuk a szervletek init() metódusát, annak szerepét. Említettük, hogy a paramétere információkat tartalmaz a szervlet futási környezetéről. Ez a gyakorlatban azt jelenti, hogy a szervlet programot futtató szerver különféle úgynevezett paraméterváltozókon keresztül közli a szervlettel a munkakörnyezetének fontosabb jellemzőit.

 a.) Szervletparaméterek:  Szervletparamétereket a szervletek konfigurálására, illetve inicializálására lehet felhasználni. A paraméterek megadási formája paraméternév= paraméterérték alakú. A paraméterfáljt a webszerver általában csak az indításkor, egyszer olvassa be, ezért az esetleges változtatások csak a webszerver újraindításakor lépnek életbe.

Jelenleg két szervletparamétert használ a futtató környezet:

·         Szervlet neve: servletnév.code=servlet osztályának teljes neve – ennek beállítása után a megadott névvel lehet hivatkozni a szervletre. Ezen név a webszerverhez küldött URL-ben, illetve további szervletparaméterek megadásakor is használható. Ha nem adunk meg nevet egy szervlethez, akkor alapértelmezés szerint annak neve meg fog egyezni a szervlet osztályának nevével.

·         Szervlet inicializációs paraméterei: servletnév.initArgs=paraméterek – az így megadott paramétereket a szervlet megkapja az inicializálásakor.

A szervlet inicializálásakor kapott ServletConfig paraméteren keresztül a szervlet inicializációs paramétereit (getInitParameter és getInitParemeterNames metódusokkal), valamint a szervletet futtató környezetet reprezentáló ServletContext (getServletContext metódussal) objektumot lehet lekérdezni. Mivel a GenericServlet automatikusan kezeli a ServletConfig objektumot, ezért ezen három metódus magára a szervletre is meghívható.

  public interface ServletConfig{

   public ServletContext getServletContext();

   public String getInitParameter(String paraméternév);

   public Enumeration getInitParameterNames();

  }

A getInitParameterNames() metódus visszaadja azoknak a paramétereknek a nevét, amelyekhez a futtató környezet rendelt valamilyen értéket, a visszaadott neveken a java.util.Enumeration interfész metódusaival mehetünk sorba. Egy adott nevű paraméter értékét a getInitParameter() metódussal kérdezhetjük le, a metódus az egyetlen paraméterében megkapott nevű paraméter értékét adja vissza. [4]

A getParameterValues egy String-ben megkapja a paraméter nevét és visszaad egy String-tömböt, amely e paraméter értékeinek  halmaza. Ez azt jelenti, hogy a paramétert még akkor is egy tömbből kell kivennünk, ha teljesen biztosak vagyunk benne, hogy csak egyetlen értéke lehet.

Ez azért kell, mert egyes HTML formaelemek úgy működnek, hogy egy paraméternévhez több értéket rendelnek hozzá. A getParameterValues metódus egyszerűen csomóba köti a paraméternévhez rendelt összes felvehető értéket és egy String tömbben adja vissza őket. Ez egyszerűbbé teszi az API-t, megengedvén egy metódusnak, hogy mind egyértékű, mind többértékű paramétereket kezelhessen. Ezen kívül a paramétereket kissé öndokumentálóbbá is teszi azáltal, hogy nem kell egy Reflection API-t definiálni, hogy megtudjuk a paraméter származási helyét és a lehetséges értékeinek számát. Ez a képesség a getParameterNames metódussal kapcsolatosan arra használható, hogy a szervletünk olyan paramétereket is felderítsen, amelyeket a kérésben nem várhatott.

Arra mindig van esély, hogy a felhasználó üresen hagy egy mezőt. Ilyenkor ellenőrízni kell, hogy a paraméter neve létezik-e, és van-e érvényes paraméterérték. Ez úgy történik, hogy a getParameterValues által String-tömbben visszaadott értékeket ellenőrizzük. Tipikusan üres mezőre utal, ha nincs tömb vagy az első String nulla hosszúságú.   [3]

A getServletContext() metódussal egy szervlet objektum hozzáférhet a futtató környezete által nyújtott néhány hasznos szolgáltatáshoz. A metódus által visszaadott objektum a javax.servlet.ServletContext interfészt implementálja. Ez az interfész olyan metódusokat tartalmaz, amelyekkel a rendszerben inicializált többi szervletről kapunk információkat, valamint ezek segítségével lehetőség van események naplózására is.

  public interface ServletContext{

   public Servlet getServlet (String nev) throws ServletException;

   public Enumeration getServlets();

   public void log (String uzenet);

   public String getRealPath (String utvonal);

   public String getMimeType (String fajlnev);

   public String getServerInfo();

   public Object getAttribute (String attributumnev);

  }

A getServlet() metódus segítségével megkaphatjuk a paraméterében megadott nevű szervlet objektum Java objektumreferenciáját. Ha a megnevezett szervlet (még) nincs a rendszerben, akkor ez a metódus null értékkel tér vissza. A metódus javax.servlet.ServletException kivételt vált ki, ha a megnevezett szervletet nem lehetett a betöltési kísérlet során inicializálni. A getServlets() metódus visszaad egy java.util. Enumeration interfészt implementáló objektumot, amely az összes elérhető szervlet referenciáját tartalmazza.

A log() metódussal írhatunk egy üzenetet a szervlet eseménynaplójába.

A getRealPath() metódus visszaadja a paraméterében megadott virtuális szerverelérési útvonalnak megfelelő valódi elérési útvonalat a megfelelő álneveknek a virtuális elérési útvonalra történő alkalmazásával, vagy null értékkel tér vissza, ha a virtuális útvonalakat a szerver nem támogatja, vagy a virtuálisról valódi elérési útvonalra konverzió valamilyen oknál fogva nem sikerült.

A getMimeType() metódus a paraméterében megadott nevú fájl MIME-típusát adja vissza, ha azt a fájl nevéből vagy tartalmából ki tudja következtetni. Ha nem tudta ezt kikövetkeztetni akkor null értékkel tér vissza.

A getServerInfo() metódussal a szervletet futtató szerverről kaphatunk vissza információkat.

A getAttribute() metódussal a szerverről további információkhoz is hozzáférhetünk, amelyekhez az eddig bemutatott metódusokkal nem lehetett hozzáférni.

A szervlet inicializálásakor érdemes a szervlet teljes futási ideje alatt használt mezőket beállítani, például adatbázis-kezelő szervlet esetén itt érdemes megnyitni az adatbázsikapcsolatot.

Kliens kérésének és a válasz absztrakciója

Miután a webszerver inicializálta a szervlet egy példányát, az képesé válik a kliens kérések kiszolgálására. Ha a webszerver megállapította, hogy egy kérés egy szervletet céloz  meg, meghívja annak public void service (ServletRequest, ServletResponse) metódusát. Az első paraméterként kapott objektumon keresztül a kliens-szervlet, míg a második paraméterként kapott objetumon a szervlet-kliens irányú kommunikáció valósítható meg. Tehát a szervlet a kliens kérésével kapcsolatos információkat a service() metódusának első paraméterében kapja meg, melyben egy javax.servlet.ServletRequest interfészt implementáló objektumot kap. A szervlet ennek metódusait meghívva hozzájuthat a kliens kérésében küldött információkhoz.  A szervlet tehát úgy szolgál ki egy kliens kérést, hogy feldolgozza az esetleges kapott paramétereket, melyek rendszerint HTML űrlapok használata esetén az űrlap mezőinek értékeit tartalmazzák, majd dinamikusan legenerál (általában) egy HTML oldalt, melyet a kliens böngészőprogram megjelenít.

A ServletRequest interfész a klienskérés paramétereinek és jellemzőinek, a kliens gép címének, a kérést kiszolgáló szerver gép címének, valamint a kérés tartalmának olvasását lehetővé tevő metódusokat definiál. A kérés tartalmát adatfolyamként egy ServletInputStream objektum reprezentálja. HttpServlet esetén a klienskérést egy HttpServletRequest objektum tartalmazza.

HTML űrlapok tartalmát szintén paramétereken keresztül kapja meg a szervlet. A paraméter neve a HTML űrlap beviteli mezőjének nevével egyezik meg, a paraméter értéke pedig a beviteli mező tartalmát veszi fel. Tehát csakis a névvel rendelkező beviteli mezők értékét tudja átvenni a szervlet.

A szervlet válaszát a service() metódusának második paraméterében levő javax.servlet.ServletResponse interfészt implementáló objektum megfelelő metódusait meghívva juttathatja vissza a klienséhez.

A ServletResponse interfész a szervlet válaszának jellemzőit beállító, valamint a válasz kiírását lehetővé tevő metódusokat definiál. A válasz tartalmát adatfolyamként egy ServletOutputStream objektum reprezentálja.  HttpServlet esetén a szervlet válaszát egy HttpServletResponse objektum tartalmazza. A szervlet válaszát csak azután küldi el a webszerver, miután lezártuk a választ reprezentáló adatfolyamot annak close metódusával. Ha még a teljes adatfolyam lezárása előtt szeretnénk, hogy a kliens böngészőprogram megkezdje az addig generált válasz megjelenítését, akkor használjuk a ServletOutputStream flush metódusát. Ekkor a böngésző a válasznak csak azon prefixét képes megjeleníteni, melynek grafikus megjelenítése már nem fog megváltozni, tehát például, ha szöveg esetén lezártuk azt egy sorvége jellel. Megjegyzendő, hogy HttpServletResponse esetén a HTTP mező fejléceit csakis a válasz adatfolyamhoz történő első hozzáférés előtt szabad állítani. Ha a válasz hosszát előre tudjuk, akkor érdemes azt beállítani a setContentLength metódussal, mivel ilyenkor a webszerver és a kliens közti adatátvitel sokkal gyorsabb lesz

Szervletek származtatása a GenericServlet osztálytól

Egy általánosan használható szervlet ősosztály a javax.servlet.GenericServlet. Ez az osztály implementálja mind a javax.servlet.Servlet, mind pedig a javax.servlet.ServletConfig interfészek metódusait. Biztosítja az init(), illetve a destroy() metódusok egy egyszerű implementációját.

A getServletConfig() metódus visszaadja az init() metódus paraméterében kapott objektumpéldányt.

A getServletContext() metódus az init() metódus paraméterében korábban kapott objektumot adja vissza visszatérési értékként.

A getServletInfo() metódus implementációja egy null értékkel tér vissza. A származtatott osztályokban ezt illik felüldefiniálni úgy, hogy az illető szervletről adjon vissza információkat (a szervlet nevét, készítőjének nevét, a szervlet verziószámát, stb.)

A service() metódus egy absztrakt metódus, vagyis a leszármazott osztályok példányosíthatóságának érdekében a leszármazott osztályban felül kell definiálni.

A javax.servlet és a javax.servlet.http csomagok architektúrája

A javax.servlet osztályokat és interfészeket bocsát rendelkezésünkre a szervletek írásához. A legfontosabb interfész a Servlet interfész. Az összes szervletnek ezt az interfészt kell implementálnia, legtöbbször a HttpServlet kiterjesztéseként.

A Servlet interfész olyan metódusokat definiál, amelyek segítségével kivitelezhető a kommunikáció a kliensekkel. Abban a pillanatban amikor egy szervlet elfogadja a kapcsolatot egy klienssel, két objektumot kap:

·       egy ServletRequest objektumot, amelyik a kliens – szerver kommunikációért felelős

·       egy ServletResponse objektumot, amelyik a szerver-kliens kommunikációért felelős.

A ServletRequest interfész a következő dolgokat bocsátja a szervlet rendelkezésére:

·       információkat a klienstől kapott paraméterekről, a kliens által használt protokoll, a hostnév, amelyiktől elfogadta a kérést

·       egy ServletInputStream belépő fluxus. Ezt a szervlet a kliensektől kapott adatok olvasására használja. A kliensek a HTTP protokoll PUT és POST metódusait használják.

A ServletResponse interfész metódusokat deklarál, amelyek segítségével a szervlet válaszokat tud küldeni a kliensek kérdéseire.

·       biztosítja a válasz hosszúságának meghatározását valamint ennek a MIME-kódját

·       biztosít egy kimenő ServletOutputStream és egy Writer fluxust, amelyeken keresztül el tudja küldeni a válaszokat a kérdésekre

Szervlet megszüntetése

Egy szervlet inicializálása után a webszerver úgy dönthet, hogy nincs többé szükség az adott szervlet szolgáltatásaira, és megszünteti a szervlet példányt. Ilyenkor a szervlet futtatókörnyezet megvárja, míg az adott szervletet használó minden még futó klienskiszolgáló programszál véget ér (vagy egy beállított időtartam, általában 30 másodperc le nem telik), és meghívja a szervlet public void destroy() metódusát. Ezen metódus meghívása után már nem fog egyik életciklus metódus sem meghívódni. Előfordulhat, hogy ezen metódus már akkor meghívódik, amikor a szervlet még egyetlen klienst sem szolgált ki, de az is elképzelhető, hogy a destroy() meghívásának pillanatában esetleg még több kliens kiszolgálása is folyamatban van.

A túl hosszan tartó kiszolgálásból eredő problémára megoldás lehet, ha mindig nyilvántartjuk, hogy egyszerre hány programszál tartózkodik a kiszolgáló metódusban. A destroy meghívásakor ezt egy logikai változóval jelezzük a programszálak felé, majd addig várunk, míg számlálónk segítségével meg tudjuk állapítani, hogy minden programszál befejeződött. A kiszolgálás menetét pedig felosztjuk apróbb részfeladatokra, melyek befejezése után mindig megnézzük, hogy közben esetleg meghívták-e a destroy-t. Igy elérhetjük, hogy minden futó programszál a leggyorsabban reagál  a szervlet megszüntetésére, valamint a szervlet megszüntetése előtt, miután már egyetlen programszál sem tartózkodik a kiszolgáló metódusban, biztonságosan felszabadíthatjuk a szervletünk által foglalt erőforrásokat (például adatbázis-kapcsolat lezárása).

A szervlet megszüntetése után a szervletpéldány kikerül a szervlet futtatókörnyezet ellenőrzése alól. Ha esetleg újra szükség lenne egy már megszüntetett szervletre, akkor az a szervlet egy új példányának létrehozását és inicializálását vonja maga után.

Folytatjuk...

Finta Annamária