Content extract
BMF-NIK Államvizsga Tételek Java (2006) 1. Swing (AWT – Swing közötti különbségek; MVC modell eredete, előnyei, bemutatás példán keresztül; Eseménykezelés modellje) A grafikus felhasználói felületel létrehozásához szükséges osztályokat és interfészeket a java.awt csomag tartalmazza Nevét az AWT (Abstract Window Toolkit – absztrakt ablakozó készlet) rövidítéséből kapta, ahol az absztrakt jelző arra utal, hogy a felületelemek megjelenítéséért nem a Java virtuális gép, hanem az operációs rendszer grafikus ablakozó rendszere a felelős. Ennek hátránya, hogy emiatt a felhasználható grafikus komponensek száma kevés, és a komponensek tényleges kinézete az operációs rendszertől függ. Ezen problémák kiküszöbölésére szolgál a Swing nevű grafikus programkönyvtár, amely a javax.swing csomagban található A Swing komponensek az AWT komponensekre épülnek, de kizárólag Javában íródtak, és önmaguk gondoskodnak a saját
megjelenítésüktől, ezáltal függetlenek az operációs rendszertől. Ezáltal lehetővé vált - komplex grafikus felhasználói elemek megvalósítása, - meglévő komponensek tetszőleges kombinálása, módosítása. Minden AWT komponenshez megtalálható annak Swing megfelelője, a Swing komponens neve előtt egy J betű van. MVC modell A Swing komponensek az adatmodell – megjelenítés – vezérlés (MVC – Model – View Controller) architektúrát alkalmazzák. Az MVC-nek megfelelően a grafikus felhasználói felületelemeket logikailag további három funkcionális részre tagolható: - adatmodell: a komponens által megjelenített adatok. A megjelenítés folyamán biztosítja az adatokat a megjelenítő rétegnek - megjelenítés: a komponens adatmodelljében található adatok megjelenítéséért felelős. A felhasználói eseményeket továbbítja a vezérlő rétegnek. - vezérlés: a felhasználói eseményeket feldolgozó programlogika. Az eseményekre
reagálva az adatmodell adatait változtatja meg. A Swing komponensek az MVC egy egyszerűsített változatát használják, ahol csak az adatmodell és a grafikus komponensek vannak szétválasztva. A grafikus komponens ekkor saját maga felelős a megjelenítéséért és a felhasználói események feldolgozásáért. Egy Swing komponens ilyenkor a modell és a grafikus megjelenítés közötti kommunikációt vezérli. MVC bemutatása a JList-en keresztül Listák megjelenítésére a JList osztály használható, amely nemcsak szöveget, hanem bármilyen objektumokat tartalmazhat listaelemenként. - Adatmodellje a ListModel, melyet vagy konstruktorban, vagy a setModel illetve a setListData metódussal adunk meg. Ha nem adunk meg adatmodellt, akkor nem lehet a listában adatot tárolni. - A lista legegyszerűbb megvalósítása a DefaultListModel leszármazottosztály. Ez a modell a java.utilvector metódusait valósítja meg (a megfelelő figyelőket automatikusan értesítve),
azáltal reprezentálja a lista elemeit. 1. oldal, összesen: 18 - - - A listaelemek kiválasztásának nyilvántartásáért a ListSelectionModel a felelős, melyet a setSelectionModel metódussal lehet megadni. Ezen interfész csaknem valamennyi metódusát implementálja a komponens. • Az adott indexek zárt intervallumának kiválasztását a setSelectionInterval metódussal lehet megadni (magyarul azt lehet megadni, hogy hányas indexű elemtől hányas indexű elemig lehet kiválasztani a lista elemei közül). • Az indexek már meglévő kiválasztáshoz hozzávételét az addSelectionInterval metódussal lehet elvégezni. • A kiválasztás törlésére való a clearSelection metódus. Példa: // ez azt csinálja, hogy mindig csak a páratlan számokat lehet kiválasztani // abban az esetben, ha a listában 1-től egyesével növekszenek az értékek public void setSelectionInterval (int x, int y) { for (int i=x; i<=y; i++) { String s=new
String((String)(Frame1.listagetElementAt(i))toString()); int b=Integer.parseInt(s); System.outprintln(b); if ((b % 2)!=0) { super.setSelectionInterval(x,x); } } } A ListSelectionModel interfész legegyszerűbb megvalósítása a DefaultListSelectionModel osztály. Példa: // maga a vizuális komponens JList l = new JList(); // a lista adatmodellje public static DefaultListModel lista=new DefaultListModel(); // a kiválasztás modellje DefaultListSelectionModel lm=new DefaultListSelectionModel(); // a listánk adatmodellje DefaultListModel l.setModel(lista); // a listánk kiválasztási modellje DefaultListSelectionModel l.setSelectionModel(lm); Az eseménykezelés modellje A Swing az AWT eseménymodelljét használja. Az eseményeket egy osztályhierarchia kezeli, amelynek gyökere a java.utilEventObject A Swing eseményeket a javaxswingevent alcsomag tartalmazza. Egy bizonyos típusú eseményhez a gyökérosztály egy neki megfelelő eseménye tartozik. Az események egy forrás
objektumból származnak, és egy vagy több fogadó objektumnak adódnak át a fogadó objektum megfelelő metódusának meghívásán keresztül. A program akkor válik eseményvezéreltté, ha lehetőség van a keletkezett eseményekre való reagálásra. Ennek támogatására való az ún eseményfigyelő módszer Ez a következő részekből áll: - adott esemény egy eseményobjektum ír le, például ActionEvent 2. oldal, összesen: 18 - - - - adott ActionEvent eseményre figyelő objektumokat az ActionListener interfész reprezentálja az interfész metódusai a figyelt esemény különböző típusainak bekövetkeztét, vagy az esemény bekövetkezésének különböző módjait írják le ezen metódusok paraméterként kapják az eseményt leíró ActionEvent objektumot az addActionListener és a removeActionListener metódusok biztosítják minden objektum számára a lehetőséget, hogy az eseményre figyelő objektumok regisztráltathassák magukat, vagy
törölhessék a már megtörtént regisztrációt. E két metódus paramétere mindig egy, az esemény figyelésében érdekel objektum. ha egy esemény bekövetkezik, akkor az esemény forrása értesíti az összes nála regisztrált figyelőt az ActionListener interfész valamely metódusának meghívásával. Paraméterként az aktuális eseményobjektum kerül átadásra. Az értesítési sorrend független a regisztrálási sorrendtől. ha egy eseményre reagálni szeretnénk, akkor előbb implementálni kell a megfelelő eseményfigyelő interfészt, majd regisztráltatni kell az implementáló objektumot az eseményforrásnál. Minden olyan eseményfigyelő interfészhez, amely több metódust is definiál, tartozik egy adapter osztály. Az ActionListener eseményfigyelő interfész adapter-osztálya az ActionAdapter osztály. az actionPerformed az ActionListener egy metódusa. 2. JavaBeans (Szoftver komponensként való felhasználhatósága; Implementációs feladatok:
szerializálható, setter, getter minta) Mit, miért A Java Beans egy komponensszemléletű bővítés a Jávához. Teljes egészében Jávában íródott, így aztán a létező böngészőprogramokkal kompatibilitási problémák nélkül használható kell legyen. Ezen HTML oldal írásakor a Java Beans-ból csupán az API (Application Program Interface) specifikációja van kész, 1996 decemberére ígérik az első használható változatot Solaris és Windows 95 platformra. A komponensalapú programozás igen általános módszer, néhány főbb alkalmazása például a következő : 1. Újrafelhasználható szoftver komponensek alkalmazásgenerátorok számára Ez a közelebbi cél, a jelenlegi Beans API ezt támogatja. 2. Jáva appletek együttműködése egymással vagy a Web-lap ill a böngésző egyéb komponenseivel (script-ek, plug-in-ek). A Beans API olyan technológiákat fed el szabványos interfészével, mint a Netscape LiveConnect rendszere. 3. Java programok
összekapcsolása jelenlegi komponensalapú rendszerekkel Ez lehetővé tenné, hogy Jáva program konténeralkalmazás vagy beágyazott objektum legyen pl. OLE vagy OpenDoc alapú rendszerekben. Praktikusan ez azt jelenti, hogy pl Windows környezetben Java program együttműködhet bármilyen OLE alkalmazással, pl. az Office programokkal. Jelenleg ennek a részletei nem ismertek, ez a távolabbi cél A Beans API-ról azt ígérik, hogy támogatni fogja a következő komponensalapú rendszereket: OpenDoc, OLE, ActiveX. 4. Hálózaton elosztott alkalmazások készítése A Beans API együttműködik olyan rendszerekkel, mint pl. a CORBA és egységes felületet nyújt elosztott alkalmazások számára 3. oldal, összesen: 18 Részei/Kapcsolódó API-k: 1. Introspection API: Automatikus komponensanalízis 2. Object Serialization: Jáva objektumok tárolása, aktuális állapotban elmentése és feltámasztása, átküldése a hálózaton. 3. AWT fejlesztések: Clipboard, Drag and
Drop, nyomtatás Ezek azt célozzák, hogy Jáva alkalmazások konténerei lehessenek más komponensalapú rendszereknek. Java Beans "mag": 1. Új eseménymodell 2. "Property"-k, futás közben másik komponens által beállítható és lekérdezhető változók 3. Introspection API: komponensek által fogadott és küldött üzenetek és property-k automatikus felderítése. Hogyan: példa alkalmazásgenerálásra komponensekből 1. A felhasználó megveszi az alkalmazásgenerátort és egy komponensgyűjteményt A komponensgyűjteményben feltámasztásra váró komponensek vannak egy archivumfájlban (JAR) elmentve. A felhasználó kiválogatja a felhasználni kívánt komponenseket és hozzáadja az alklamazásgenerátor komponensgyűjteményéhez. 2. A felhasználó elrendezi a felhasználni kívánt komponenseket A készülő appletbe "dobálja" a komponenseket, a komponensek inicializálhatják magukat a JAR fájlba mentett állapot szerint. A
komponensek emellett saját inicializálóeljárással rendelkezhetnek, amelyek segítségével a felhasználó megadhatja a komponensek tulajdonságait. 3. Komponensek összekötése Ez a jelenlegi példában történhet szövegesen; a készülő applet kódjában a felhasználó kitölti azoknak az eljárásoknak a törzsét, melyek a komponenseket összekötik. 4. Alkalmazásgenerálás A felhasználó az elkészült alkalmazást aktuális állapotában elmenti Végeredményben a komponensek .class fájljai egy JAR állományba kerülnek Az alkalmazásgenerátor egy Web-oldalt is legyárt, amellyel az applet kipróbálható. Eseménymodell Új eseményobjektumok: mind az java.utilEventObject osztály leszármazottjai Eseményfogadók java.utilEventListener interfészből leszármazott interfészeket implementálnak, ezzel jelzik, milyen esemény(eket) kívánnak fogadni. Eseményforrások olyam metódusokat implementálnak, amelyek segítségével az eseményfogadók
regisztrálhatják magukat az eseményforrásnál. Adaptorosztályok használhatók akkor, ha a források és fogadók nem köthetők össze közvetlenül vagy különleges kezelés (pl. eseménysor buffer) szükséges Példa egy egyszerű eseményre, fogadójára és küldőjére. 4. oldal, összesen: 18 public class KeyKlickedEvent extends java.utilEventObject { protected int key; KeyKlickedEvent( int newkey ) { key = newkey; } } Fő előnye az új EventObject-nek, hogy a régi Event osztállyal szemben tetszőleges számú és típusú saját mezője lehet, továbbá az üzeneteket ezentúl az osztály típusa alapján lehet megkülönböztetni. Az eseményfogadó egy EventListener-ből leszármazott interfészt implementál. Ebben az interfészben fogja össze az eseményfogadó metódusait. Példa: interface KeyKlickedListener extends java.utilEventListener { void KeyKlicked( KeyKlickedEvent ke ); } Két dolog fontos itt: az egyik, hogy az interfész az EventListener-ből
származik, a másik az eseményfogadó metódus "aláírása", vagyis visszatérési értéke, nevének formája, paramétereinek száma és típusa. Eseményfogadó metódusoknál ez az aláírás a következő formájú: void <metódusnév> ( <eseménytípus> ); Végül az eseményt generáló objektumnak implementálnia kell olyan eljárásokat, melyeknél az eseményfogadók regisztráltathatják magukat. Például egy KeyKlickedEvent-eket generáló osztály a következő metódust implementálhatja. public KeyKlickedListener setKeyKlickedListener ( KeyKlickedListener kkl ) { . } Látható, hogy az eseményküldő regisztrációs metódusának aláírása a következő formájú: public <interfész típus> set<interfész típus>( <interfésztípus> ) Teljességgel a komponenst író felelőssége az üzenetek generálásának és fogadásának megfeleló kezelése, maga a Java Beans semmiféle belső üzenetkezelővel nem rendelkezik ! A
Beans csupán az üzenetek, generátoraik és fogadóik kinézetét, "aláírását"rögzíti. 5. oldal, összesen: 18 Property-k A property olyan változó, amelyet a komponens elérhetővé tesz a többi komponens számára. Hasonlóan az eseménymodellhez, a Beans itt is csupán a property-ket manipuláló eljárások "aláírásait" rögzíti. Egy property-hez kell tartozzon egy beállító és egy lekérdező eljárás annak a komponensnek a törzsében, amelyikhez a property tartozik. Az aláírás a következő formájú: public <típus> get<property név>(); public set<property név>( <típus> ); A <típus> a property-t reprezentáló Java típus, a property név pedig az a név, ahogy a property-t a külvilág ismeri. Példa: public Color getBackground(); public setBackground( Color ce ); A fenti példa egy komponens Background property-jét beállító és lekérdező eljárásainak fejét mutatja. Egy property eseményt
generálhat, ha beállítják vagy visszautasíthatja bizonyos határokon kívüli értékre beállítását. Introspection Futásidőben vagy az alkalmazásgenerátorban ki kell derítenünk, milyen eseményeket és property-ket kezel az adott komponens, erre szolgál az Introspection API. Egy komponens leírhatja önmagát egy BeansInfo struktúrában, ekkor az itt leírt tulajdonságai ismertek a környezet felé. Ha ezt nem teszi, az Introspection alrendszer "felderíti" a komponenst a kötelező aláírásformátumok alapján. 3. JDBC (Feladata, driverek típusai, 1-4; alapvető JDBC osztályok; mely SQLutasításhoz melyik használható) 6. oldal, összesen: 18 Feladata Java nyelven egyszerű kliens-szerver architektúrájú adatbázis-kezelő programokat létrehozni, ezért felmerült az igény, hogy a Java programok kommunikálni tudjanak a legkülönfélébb adatbázisokkal is. Ezt biztosítja a JDBC A JDBC egy programozói interfész (API) SQL utasítások
végrehajtására. Két részből áll: - JDBC alap-API: az adatbázisok eléréséhez szükséges alapvető típusok leírása, ezek a java.sql csomagban találhatóak - JDBC standard kiterjesztés API: további, magasabb szintű típusok leírása a javax.sql csomagban A JDBC API szolgáltatásai: - összekapcsolódás relációs adatbázissal - SQL utasítások végrehajtása - SQL lekérdezések eredményének feldolgozása JDBC meghajtóprogramok (driverek) 1. JDBC-ODBC áthidalóprogram + ODBC meghajtóprogram: már létező ODBC meghajtóprogram használatát teszi lehetővé JDBC hívások kiszolgálására. 2. JDBC-saját kliens-API áthidaló / meghajtóprogram: a meghajtóprogram a JDBC hívásokat közvetlenül átalakítja a megfelelő adatbázis kliens-API hívásaira. A kliens gépen ott kell lennie a megfelelő adatbázis kliens-API-t megvalósító bináris programnak. 3. JDBC-hálózati protokoll Java meghajtóprogram: a Javában írt, hordozható meghajtóprogram a
JDBC hívásokat adatbázisfüggetlen hálózati protokollhívásokká alakítja, melyeket egy megfelelő szerverprogram értelmez és alakít át az adott adatbázis-kezelő API-jának hívásaivá. Ebben az esetben a JDBC-kliens nem közvetlenül az adatbázissal, hanem egy külön szerverprogrammal kommunikál. 4. JDBC-saját protokoll Java meghajtóprogram: szintén Javában írt meghajtóprogram, amely a JDBC hívásokat közvetlenül a megfelelő adatbázis-kezelő adatmanipulációs protokolljának hívásaivá alakítja át. Nincs szükség közbenső szerverprogramra Alapvető JDBC osztályok DriverManager - a megfelelő meghajtóprogram kiválasztását és használatát segíti - nyilvántartja a használható összes regisztrált meghajtóprogramot, és az adatbáziskapcsolat kérésekor a megfelelőt aktivizálja Connection - a program és az adatbázis közötti kapcsolatot egy Connection objektum reprezentálja - az adatbázis-kapcsolat felévtele: Connection
con=DriverManager.getConnection(url,id,pass) Statement - egyszerű SQL utasítások végrehajtására és a visszaadott eredmények feldolgozására szolgáló interfész - a Connection objektum createStatement() metódusa hozza létre a Statement objektumot Statement stmt = con.createStatement() - egy Statement objektumot háromféleképpen is végre lehet hajtani: 7. oldal, összesen: 18 • • • executeQuery: a paraméterben megadott SQL utasítást végrehajtja, és egy annak eredményét reprezentáló eredménytábla (ResultSet) objektumot ad vissza. Lekérdező utasítások (SELECT) végrehajtására használható execeteUpdate: a paraméterben megadott SQL utasítást végrehajtja, és a megváltoztatott sorok számát adja vissza. Adatmanipulációs (INSERT, UPDATE, DELETE) és adatdefiníciós SQL utasítások végrehajtására használható. execute: a paraméterben megadott SQL utasítást hajtja végre. Akkor használható, ha az SQL utasítás többfajta
eredményt is visszaadhat, vagy nem ismert, hogy milyen típusú a visszaadott eredmény. PreparedStatement - a Statement interfész kiterjesztése - az interfész egy példánya már tartalmaz egy SQL utasítást, előfordított formában - az SQL utasítás tartalmazhat bemenő paramétereket is. A paramétereket kérdőjelek jelölik. Végrehajtás előtt minden paraméternek értéket kell adni a megfelelő set metódussal: stmt.setString(1,”kutya”) - létrehozása: PreparedStatement stmt = con.prepareStatement( "SELECT nev FROM szemely WHERE cim = ? "); - végrehajtása: ugyanaz, mint a Statement-nek ResultSet - az eredménytábla - feldolgozása: ResultSet rs = stmt.executeQuery(); while (rs.next()) { feldolgozás } - pozícionálás az eredméyntáblában (mindegyik hamisat ad vissza, ha nem lehet végrehajtani): • next: a következő sor • previous: ez előző sor • last: az utolsó sor • first: az első sor • afterLast: az utolsó sor után •
beforeFirst: az első sor előtt • absolute: adott számú sorra • relative: relatívan - ilyenek is vannak: • isAfterLast • isBeforeFirst • isFirst • isLast • getRow: az aktuális sor száma 4. Web Container (http request és response; webalkalmazás felépítése; hogyan futtatja a Tomcat a servleteket; hány példány jön létre a servletekből) 8. oldal, összesen: 18 HTML A HTML lehetőséges biztosít arra, hogy az Interneten publikált információinkat, dokumentumainkat a világ bármely pontján levő számítógép értelmezni tudja. Az SGML (Standard Generalized Markup Language, ISO 8879) egy olyan rendszer, amelynek segítségével ún. jelölőnyelveket lehet definiálni A dokumentumok szerzői különböző jelölésekkel adják meg a szerkezeti, prezentációs és szemantikai információkat. A HTML az SGML tipikus alkalmazása. Minden SGML alkalmazás a következőkkel írható le: 1. 2. 3. SGML deklaráció. Ez meghatározza, hogy mely karakterek
és elválasztók jelenhetnek meg az alkalmazásban. Dokumentum Típus Definíció (DTD). Ez a jelölőszerkezetek leírását tartalmazza, ezen kívül karakterhivatkozásokat is magába foglalhat. Specifikáció, amely megadja a szemantikai szabályokat. Minden SGML alkalmazás deklarál elemtípusokat, amelyek struktúrákat vagy viselkedésmódokat határoznak meg, a HTML esetében például paragrafusokat, hipertext linkeket, listákat, táblázatokat, képeket, stb. Minden elemtípus deklarációja alapvetően három dolgot tartalmaz: egy ún. kezdő tag-et, az elem tartalmát és a befejező tag-et. A tag-eket a szemléletesség kedvéért úgy is felfoghatjuk, mint egyfajta címkéket. Ezek a címkék határozzák meg a HTML dokumentumban az egyes elemek elejét, végét és a két címke közti tartalmat, amelyre az elem vonatkozik. A tag-et és az elem attributumaihoz rendelt értékeket a szövegben < és > határolójelek közé írjuk. Ezek nem jelennek meg a
megjelenítés során, hanem a kezdő és befejező tag között lévő tartalom valamilyen jellemzőjét módosítják. HTTP A HTTP protokoll a hypertext dokumentumok letöltésére szolgál. A szerverek és a kliensek közti kommunikációt definiálja. TCP kapcsolaton alapul, minden lap letöltésekor új TCP kapcsolat jön létre, ami az átvitel után lebomlik. Az elérendő erőforrást az URL (egységes erőforrás azonosító) azonosítja: http://számítógép neve:port/fájlnev?paraméterek Működése: - a kliens felveszi a kapcsolatot a szerverrel, majd elküldi a kérését (azt, hogy mivel és mit kell csinálni) - a szerver végrehajtja a kérést, és visszaküldi a válaszát - ha a szerver nem tudja végrehajtani a kérést, akkor ennek okát közli a klienssel - a HTTP kérés és válasz ún. HTTP-fejlécmezőket is tartalmaz A HTTP fejlécmezők A REQUEST részei: 9. oldal, összesen: 18 - request-line: GET/POST <Space> absolute-url <Space>
(HTTP/1.0|HTTP/11) HTTP-fejléc(header): (general-header|request-header|entity-header) a kérés törzse (body) A RESPONSE részei: - status-line: HTTP/1.1 <Space> status-code+reason-phrase - - status-code+reason-phrase = 200 <Space> OK | 400 <Space> Bad Request | 404 <Space> Not Found | 500 <Space> Internal Server Error | 501 <Space> Not Implemented HTTP-fejléc(header): (general-header|response-header|entity-header) general-header = Date: <Space> date Connection: <Space> close response-header = Server: <Space> vendor-string entity-header = Content-Length: integer-greater-or-equal-0 Content-Type: <Space> text/html Last-Modified: <Space> date [ Cache-Control: <Space> no-cache] // only for dynamic pages [ Expires: <Space> date <CRLF> ] // only for dynamic pages a válasz törzse (body) WEB-alkalmazás felépítése Webmodul1 (egy nagyobb egység, mint például egy komplett weboldal) index.html
index.jsp valami.gif . WEB-INF classes servlet / jspproject *.class jspproject *.class lib *.jar web.xml web.inf <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://javasuncom/dtd/web-app 2 3dtd"> - <web-app> <display-name>WebModule1</display-name> - <servlet> <servlet-name>servlet1</servlet-name> <servlet-class>loginservlet.Servlet1</servlet-class> </servlet> - <servlet> 10. oldal, összesen: 18 <servlet-name>masikservlet</servlet-name> <servlet-class>loginservlet.masikServlet</servlet-class> </servlet> - <servlet-mapping> <servlet-name>servlet1</servlet-name> <url-pattern>/servlet1</url-pattern> </servlet-mapping> - <servlet-mapping> <servlet-name>masikservlet</servlet-name>
<url-pattern>/masikservlet</url-pattern> </servlet-mapping> </web-app> A Tomcat hogyan futtatja a Servleteket? TOMCAT SERVLET CLIENT THREADPOOL T1 T2 A TOMCAT egy webszerver. Egy TOMCAT-en több szervlet is futhat egyszerre Minden szervlet egyszer töltődik be a memóriába, így az összes kliens ugyanazt a szervletet használja, csak külön szálon. A szervlet annyi kliens tud kiszolgálni, ahány szál kezelésére képes Kétféle módon lehet biztosítani, hogy egy metódust egyszerre csak egy szál tudjon elérni: - a syncronised kulcsszó használatával - a SingleThreadModel interfész implementálásával. Ez biztosítja, hogy a kiszolgáló service metódust egyszerre csak egy szál hívja meg. 5. Servlet (Servlet-CGI összehasonlítás: előnyei abból, hogy folyamatosan a memóriában van; életciklus, request, response, paraméterek kezelése; session, hogyan azonosítja a felhasználót) CGI A nagy ötlet az, hogy bizonyos webcímek mögött
nem egy előre elkészített ("statikus") tartalom, hanem egy program rejtőzik, ami a böngésző kérése alapján meghívódik és röptében generál egy változó ("dinamikus") válaszdokumentumot. A CGI-program egyszerűen a szokásos bementi csatornáján ("standard input") vagy egy környezeti változón keresztül kapja meg a felhasználó kérését és válaszát a kimeneti csatornájára ("standard output") írja. A specifikáció tartalmaz egy adag környezeti változót is, amit a webszerver a program meghívása előtt beállít a program számára és amelyekből a 11. oldal, összesen: 18 program mindenféle okosságokat olvashat ki a kérésre vonatkozóan. Az elkészült programokat egyszerűen be kell másolni a webszerver egy megfelelően konfigurált könyvtárába és már készen is van a webalkalmazás. Minden egyéb, hálózatkezeléssel kapcsolatos problematika már a webszerver vállát nyomja. A HTTP protokoll
szabványa definiálja, hogyan tárgyal a böngésző és a webszerver egymással. Két alapvető módszer van, amellyel a kliens a szervernek adatot küldhet, ezeket a megfelelő HTTP parancs nevéről GET és POST metódusnak nevezik. Lényegileg mind a kettő azonos, a különbség ott van, hol utaznak a webszervernek küldött adatok. A GET metódusnál magához a webcímhez fűzik egy kérdőjel után, a POST metódusnál a HTTP kérés törzsébe ágyazzák. A CGI-program a kimenetére kell írja először a HTTP fejléc általa beállított részeit, majd egy üres sor után magukat az adatokat. A CGI-nek egyszerűsége mellett problémái is akadnak, mindenekelőtt zabálja a gépkapacitást, úgy a memóriát, mint a gépidőt. Minden CGI-kérésre egy teljesértékű processz lódul meg, betöltődik, memóriát foglal, csak azért, hogy kiírjon néhány karaktert, majd hasonlóan nagy felhajtással távozik. Ha a program scriptben íródott, akkor minden egyes kérésnél a
script értelmezőprogramja is betöltődik, fejlettebb rendszernél (pl. Perl) csak egyszer, de shell scriptnél minden kérésre betöltődik, majd távozik egy shell processz. Szervlet A szervlet egy speciális Java program, amely a webszerverrel együttműködve a szerveroldalon lehetővé teszi HTML oldalak dinamikus létrehozását és paraméterezését. A szükséges osztályok és interfészek a javax.servlet csomagban találhatóak Azok a szervletek, amelyek a HTTP protokollt használják, a javax.servlethttphttpServlet leszármazottjai A szervlet előnyei a CGI programmal szemben: - platformfüggetlen, hiszen Javában íródik - a webszerveren belül állandóan futó virtuális gép sokkal gyorsabb kiszolgálást eredményez, mintha minden kérés kiszolgálásához külső programindítás történne - a virtuális gép miatt leegyszerűsödik a kéréskiszolgálások szinkronizációja - a szervlet átirányíthatja a kérést egy másik szervlethet, ezáltal dinamikusan
lehet alkalmazkodni a webszerver terheltségéhez - egy szervlet könnyen megőrzi az információkat az azonos helyről jövő egymás utáni kérések kiszolgálása között A szervlet csak egyszer töltődik be, majd mindaddig a tárban marad, amíg ki nem töltik onnan, általában az adminisztációs programmal. A szervlet betöltődésének időpontját a Java Webszerverben be lehet állítani, meg lehet mondani, hogy egy szervlet már a szerver betöltődésekor kerüljön a tárba vagy csak akkor, amikor először hivatkoznak rá. Meg lehet csinálni, hogy a szervlet emlékezzen az előző hívásokra. A HTTP tranzakcióelvű, a kérés után jön a válasz, majd a kapcsolat lezárul. A kapcsolat felépítése és lezárása azonban mindenhol, a TCP/IP-ben is időbe telik, így ha folyton lezárjuk a kapcsolatot a kliens és szerver között, sokba kerülhet nekünk. Alapvetően erre nincs szükség a böngészők és szerverek "keepalive" szolgáltatása miatt. Mind
a szerver, mind a böngésző megpróbálja életben tartani a kapcsolatot, hogy esetleg egy újabb HTTP tranzakciót indíthasson rajta. Mindkét oldalnak jogában áll lebontani, de ha a "keepalive" engedélyezve van, törekedni fognak, hogy ezt ne kelljen megtenniük. 12. oldal, összesen: 18 A trükk azon alapszik, hogy a szerverek a HTTP fejlécben megmondják, mennyi adatot küldenek, így a böngésző tudja, mikor ért véget a válasz, még ha a szerver nem is bontja le a kapcsolatot. A probléma csak akkor van, ha a szerver nem küldi el az üzenet hosszát, mert ekkor tényleg csak abból tudni a tranzakció végét, hogy a szerver lebontotta a kapcsolatot. Életciklus Amikor a szervlet betöltődik a tárba, inicializálódik inicializációs paraméterek alapján és ezeknek a feldolgozása lehet az init metódusban (példányosítás). Betöltődött szervlet hívásokat kaphat, ekkor a service nevű metódusa hívódik meg. Majdnem minden lényeges dolog a
service metódusban történik. Ez két paramétert kap, egyik paraméterobjektuma a kérést, másik a rá adandó választ jelképezi. Amit CGI-ben a környezeti változók kiolvasásával tudtunk meg, itt a HttpServletRequest objektum mezői és metódusai mondják el. Amit régen a kimenetre írtunk, azt most a HttpServletResponse objektum kezeli Itt most a következő történik: beállítjuk a válasz típusát text/html-re, majd megnyitjuk a kimeneti csatornát és beleírjuk a generált HTML dokumentumot. A ServletRequest intefé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ást lehetővé tevő metódusokat definiál. 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 HttpServlet implementálja a service metódust, és a HTTP klienskéréseket azok HTTP
típusától függően a következő metódusokhoz továbbítja: - doGet (HttpServletRequest, HttpServletResponse) - doPost (HttpServletRequest, HttpServletResponse) Kérés átirányítása: - a HttpServletResponse sendRedirect metódusával. Ilyenkor egy abszolút URL-t kell megadni Hiba jelzése: - a HttpServletResponse sendError metódusával Végül pályafutásának befejezése előtt destroy nevű metódusát hívják meg, ez akkor lehet fontos, ha valamilyen rendszererőforrást kaparintott meg, amit vissza kell adjon. Sütik A klienshez tartozó adatokat a kliens tárolja, és azokat minden kéréskor elküldi a szervletnek. Erre való a süti. A süti szöveges információ, amelyet a kliens böngészőprogram tárol el A süti a kliensoldalon tárolódik és egy adott webszerverhez tartozik, így ha egy webszerveren több szervlet is fut, akkor mindegyik olvashatja a másikak által létrehozott sütiket. A sütik tartalmára a süti nevével lehet hivatkozni. A sütik csak
HTTP protokoll esetén használhatók, ezért minden sütivel kapcsolatos típus és metódus javax.servlethttp csomagban található A klienstől kapott sütiket a HttpServletRequest getCookies metódusával lehet lekérdezni, amely azokat egy tömbben adja vissza. Ha új sütit szeretnénk a kliensnél eltároltatni, akkor a sütit a süti létrehozása és a paraméterek megadása után a HttpServletResponse addCookie metódusával kell a kliensnek elküldeni. Már létező sütit újra el kell küldeni a kliensnek, ha annak valamelyik jellemzője megváltozott. A süti azt jelenti, hogy a szerver speciális HTTP-fejléceket küld, aminek hatására a kliens ezen fejlécek tartalmát elmenti egy kis adatbázisba. Egy süti megmondja, meddig él, ki ô és 13. oldal, összesen: 18 kire vonatkozik, valamint névvel azonosított változóértéket is visz. Valahányszor a böngészőt arra a webcím-csoportra irányítják, amire a süti vonatkozik, a böngésző HTTP-fejlécekben
elküldi a süti utolsó ismert értékét. A böngészőkben ki lehet kapcsolni a sütik fogadását vagy figyelmeztetést kérni, ha ilyet kapunk. Nem lehet tehát arra számítani, hogy sütijeinket mindig letárolják, ezért egy sütit használó programnál mindig fel kell készülni arra, hogy a süti nem jön vissza. Session Előfordulhat, hogy a sütiken alapuló információtárolás nem működik (pl. a kliens nem foglalkozik a sütik tárolására vonatkozó kéréssel). Egy másik módszer a session-ök használata. Ebben az esetben a szerver tárolja az információt Minden klienskapcsolat, amely a ugyanazt a környezetet használja, ugyanazokat az adatokat is fogja látni. A környezetet a szerver tartja nyilván, az azonosítóját (session id) eljuttatja a klienshez, majd a kliens a kapott azonosítóra hivatkozva lehetővé teszi, hogy a szerver adatokat rendeljen a klienshez, ez a kapcsolat alatt mindig elérhető lesz (a szerver a session id alapján azonosítja a
klienst minden kéréskor). Egy klienskapcsolat-környezetet a HttpSession osztály reprezentál, melynek jellemzői: - azonosító: a klienskapcsolat-környezet szöveges azonosítója, lekérdezni a getId metódussal lehet, beállítása pedig annak létrehozásakor, automatikusan történik - létrehozás időpontja - legutolsó hozzáférés időpontja - élettartam. A kapcsolatkörnyezet automatikusan megszűnik, ha annak érvényességi időtartama alatt nem történik hivatkozás rá. 6. JSP (születésének okai, hogyan fut le egy JSP lap, lap részei, JSP és Bean-ek kapcsolata; JSP hátrányai) A JSP a szervlethez hasonlóan egy klienstől érkező kérés alapján valamilyen szöveges, leggyakrabban HTML vagy XML formátumú dokumentum dinamikus, szerveroldali előállítására szolgáló technológia. Míg a szervletek esetében a Java kódban elrejtve szerepelnek a szöveget a kimenetre kiíró utasítások, addig a JSP-nél a rögzített szöveg közé rejtve
szerepelnek az oldal tartalmát módosító utasítások. Születésének oka az volt, hogy fejlesztői szerették volna a servletek programozásának nehézségeit elrejteni a programozásban kevésbé jártas emberek elől azzal, hogy szétválasztják az oldal programozási részét a tartalomtól és a designtól. A JSP lehetővé teszi a munkamegosztást, azaz hogy egyszerre több fejlesztő foglalkozzon ugyanannak az oldalnak más-más részével. Egy JSP oldalra vonatkozó kérés esetén a következő történik: - a kliens elküldi a kérést a szervernek - a web- vagy alkalmazásszerver felismeri, hogy egy JSP fájlra vonatkozik a kérés, így továbbítja azt a JSP containernek, ami általában a webkiszolgáló része - a JSP fordító a .jsp fájlból sorról-sorra haladva előállítja a neki megfelelő java szervlet forrását - a java kódot a javac fordítóval lefordítja egy .class fájlba - inicializálja a szervletet, majd a szervlet a kérést megkapva
előállítja az oldal végleges szövegét 14. oldal, összesen: 18 - a válasz végül eljut a klienshez A fordító a JSP egyszerűbb, szövegvezérelt formátumából szervlet kódot készít, és valójában ez szolgálja ki a kérést. Fordítani csak az első kérés kiszolgálásakor szükséges A JSP oldal szövegében található Java kód változatlanul bekerül a belőle készített szervlet forrásába, így a JSP megőrzi a szervletek előnyét: tetszőleges Java API vagy saját Java osztály meghívható. Egy JSP oldal könnyen kommunikál egy szervlettel, és ez fordítva is igaz. A JSP elemei A következők lehetnek: - direktívák - script-elemek - akcióelemek Minden olyan literál, amit a fordító nem ismer fel, egy az egyben bekerül az előállított oldal szövegébe. Direktívák - a JSP containernek szóló utasítások, nem módosítják az előállított oldal szövegét - a page direktíva • az egész oldalra vonatkozó jellemzőket állíthatjuk be
• a fordítási egységben bárhol előfordulhat, de az import kivételével minden attribútumnak csak egyszer adhatunk értéket • fordítási egység: ad adott oldal és az include direktívával beillesztett oldalak összessége • az attribútumok a következők: language: a script-részletekben, kifejezésekben és a deklarációkban használt programozási nyelv extends: megadja, hogy a JSP oldalból készült osztály melyik osztálynak legyen a leszármazottja import: az oldalból készülpőő szervlet import listáját egészíthetjük ki session: true vagy false értéke adja meg, hogy az oldalban akarunk-e session-t használni puffer: meghatározza az out változó pufferelésének módját info: megadhatjuk az oldal rövid leírását errorPage: annak a JSP oldalnak a címe, ahová az oldalban fellépő kivételt továbbítani szeretnénk contentType: megadja az oldal típusát és karakterkódolását - az include direktíva • adott
fájl fordítás előtti beillesztésére szolgál • a beillesztés statikus • attribútuma: file, melynek értéke egy fájlra mutató relatív URL - a taglib direktíva • a fordító által felismert kifejezések kiegészíthetők saját tagekkel, melyek könyvtárakba rendezhetőek • a direktíva segítségével adhatjuk meg, hogy a fordító hol keresse a saját elemeinket definiáló tag library descriptor-t • attribútumai: 15. oldal, összesen: 18 uri: megadja az elemkönyvtárat azonosító szimbolikus vagy tényleges URL-t prefix: azt a prefixet adja meg, amelyet egy kettősponttal elválasztva a saját elemeink neve elé kell majd tenni ahhoz, hogy hivatkozni tudjunk rájuk Script-elemek - fajtái: • deklaráció • script-részlet (scriptlet) • kifejezés - scriptletek - kifejezések • olyan script-nyelvű elemek, amelyeket a fordító String típusra hozhat, és közvetlenül a kimenetre írhat • a típuskonverzió sikertelensége esetén a
fordításkor hibaüzenetet kapunk Akciók - lehetőség van saját akciókat definiáló custom tag library-k írására, ezáltal egyszerűbben lehet kezelni a saját kódrészleteket - a saját akciók mögött egy-egy Java osztály áll, amely felhasználhatja, és általában fel is használhatja az attribútumok értékeit, valamint az implicit objektumok (például a kérés) paramétereit, és ezek alapján valamilyen szerveroldali feladatot végez el, például ír a kimenetre - fontos szerepet játszik a kód-újrafelhasználásban is, mivel akár egy oldalon belül is többször felhasználható - a <jsp:useBean> akció • többféle funkciót egyesít • lényege, hogy megpróbálja megkeresni a megadott névtérben (scope) megadott néven (id) szereplő objektumot, és az oldal script.nyelve számára szintén id néven elérhetővé tenni, type típusúra kényszerítve • használható objektumok, így JavaBeanek példányosítására is, ugyanis ha a keresés
nem jár sikerrel, akkor a class vagy a beanName attribútumok alapján megkísérli példányosítani az adott osztályt, elhelyezi a kapott objektumot a scope névtérben és az id értékeként megadott néven a scriptnyelv számára is elérhetővé teszi az új objektumot • kötelező értéket adni az id attribútumnak, valamint type és class attribútumok közül legalább az egyiknek • összefoglalva az id és a scope alapján megpróbálja megkeresni az objektumot az adott névtérben az oldal scriptnyelvében deklarál egy változót id néven és type tíoussal, ha type nincs definiálva, akkor a típus class lesz ha megtalálta az objektumot, akkor típuskényszerítéssel type típusúra hozza és értékül adja a létrehozott változónak ha az objektumot nem találta meg, és se a class, se a useBean attribútum nem volt megadva, akkor a feldolgozás véget ér ha az objektumot nem találta meg, és a class értékeként megadott osztály
rendelkezik nyilvános konstruktorral, akkor példányosítja 16. oldal, összesen: 18 ha az objektumot nem találta meg, és a beanName adott, akkor létrehoz egy új objektumot, és ezt értékül adja a script-változónak, és elhelyezi a scope által meghatározott névtérben ha a jsp:useBean törzse nem üres, akkor feldolgozza. A törzsben lévő script-elemek számára az új változó már elérhető 7. Taglib (milyen igények vezettek a létrejöttéhez; hogyan kapcsolódik egy JSPlaphoz; mit ír le a TLD, hogyan épül fel egy tag, hogyan befolyásolják a lapgenerálást a függvények visszatérési értékei) Miért taglib? A JSP a szervlethez hasonlóan egy klienstől érkező kérés alapján valamilyen szöveges, leggyakrabban HTML vagy XML formátumú dinamikus, szerveroldali előállítására szolgáló technológia. Hátránya, hogy a JSP nem különül el a HTML kódtól, ezért átláthatatlan A JSP lehetőséget biztosít saját elemkönyvtárak
(custom tag library) készítésére, ezáltal a kódok átláthatóbbá váltak, és lehetőség nyílt a kód megosztására és újrafelhasználására. További előny, hogy az elemkönyvtárak hordozhatóak, azaz az oldal programozási nyelvétől és a készítőtől függetlenül bármikor felhasználhatóak. A JSP által felismert akcióelem-készlet tehát kibővíthető saját tagekkel, melyek könyvtárakba rendezhetőek (custom tag library). A taglib direktíva segítségével adhatjuk meg a fordító számára, hogy hol keresse a saját elemeinket definiáló tag library descriptor-t. A direktívának az első saját elem előfordulása előtt szerepelnie kell. Két attribútuma van: - uri: az elemkönyvtárat azonosító szimbolikus vagy tényleges URI - prefix: kettősponttal elválasztva a saját elemeink neve elé kell tenni, csak így tudunk rájuk hivatkozni. A prefixek célja a névterek szétválasztása, amire azért van szükség, mert egy oldalba taglib
direktívákkal tetszőleges számú elemkönyvtárat „importálhatunk”. A taglib kapcsolódása egy JSP laphoz A TLD egy egyszerű szerkezetű XML dokumentum, amely a JSP containernek és a könyvtárat felhasználóknak szolgál információkkal a könyvtárról és a benne szereplő elemekről. A TLD fájl felépítése: <?xml version=1.0 encoding=iso-8859-2 ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://javasuncom/j2ee/dtds/web-jsptaglibrary 1 1dtd"> <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>mal</shortname> <tag> <name>greetings</name> <tagclass>malary.greetings</tagclass> <attribute> <name>type</name> <required>true</required> 17. oldal, összesen: 18 <rtexprvalue>false</rtexprvalue> </attribute> <attribute>
<name>time</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <tag> <name>ciklus</name> <tagclass>malary.ciklus</tagclass> <attribute> <name>count</name> <required>true</required> </attribute> </tag> <tag> <name>feltetel</name> <tagclass>malary.feltetel</tagclass> <attribute> <name>logikai</name> <required>true</required> </attribute> </tag> </taglib> Tag Saját elem készítése során először a TLD-t kell elkészíteni, majd meg kell írni az elemnek szánt feladatokat elvégző elemkezelőt. Az elemkezelő egy olyan tulajdonságokkal rendelkező JavaBean, amely megvalósítja a javax.servletjsptagext csomag Tag, vagy BodyTag interfészét. Az interfészek azokat a metódusokat tartalmazzák, amiken keresztül a JSP oldalból készült szervlet az
elemkezelő osztállyal kommunikál. A Tag intefész három metódussal rendelkezik: - doStartTag: a JSP oldalból készített szervletben ez hívódik meg a nyitóelem helyén. Az eljárás visszatérési értéke SKIP BODY vagy EVAL BODY INCLUDE lehet. Az előbbi esetben (ez az alapértelmezett) a törzs nem kerül feldolgozásra, az utóbbi esetben viszont igen. - doEndTag: a záróelem helyén hívódik meg, Két lehetséges értéke az EVAL PAGE és a SKIP PAGE. Az előbbi esetben (ez az alapértelmezett) folytatódik az oldal végrehajtása, utóbbi esetben pedig befejeződik. - release: a szervlet már végzett az elemkezelő objektummal. A BodyTag interfész legfontosabb metódusai: - doInitBody: egyszer, a törzs első kiértékelése előtt hívódik meg. - doAfterBody: a törzs minden végrehajtása után meghívódik. Ha nem volt törzs megadva, vagy a doStartTag metódus SKIP BODY értéket ad vissza, akkor egyik sem hívódik meg. Lehetőség van a törzs többszöri
kiértékelésére: amennyiben a doAfterBody EVAL BODY TAG értékkel tér vissza, akkor a törzs kódja újra végrehajtódik, ha pedig SKIP BODY-t ad vissza, akkor a törzs feldolgozása véget ér. 8. XML (eredete, létrejöttének okai, részei, alkotóelemei, szintaktika, mire használható a DTD) 9. SAX és DOM (különbségek, előnyök, hátrányok, DOM objektumok) Lásd az XML - Gondolatok a hordozható adatokról (2001, 17 oldal) című doksit. 18. oldal, összesen: 18