A WEB programozása - Szervletek dr. Gál Tibor tavaszi félév

Hasonló dokumentumok
JavaServer Pages (JSP) (folytatás)

A WEB programozása - JSP1 dr.gál Tibor őszi félév

Java Servlet technológia

Bevezető. Servlet alapgondolatok

JEE tutorial. Zsíros Levente, 2012

Hello World Servlet. Készítsünk egy szervletet, amellyel összeadhatunk két számot, és meghívásakor üdvözlőszöveget ír a konzolra.

Java technológiák - ANTAL Margit. komponensek. A HTTP protokoll. Webkonténerek és szervletek. Egyszerű HTTP. ANTAL Margit.

CREATE TABLE student ( id int NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name varchar(100) NOT NULL, address varchar(100) NOT NULL )

Adatbázisok webalkalmazásokban

Web-fejlesztés NGM_IN002_1

Interaktív weboldalak készítése

Szervlet-JSP együttműködés

Menetkövetés lehetőségei

WEBFEJLESZTÉS 2. ADATBÁZIS-KEZELÉS, OSZTÁLYOK

SZÁMÍTÓGÉPES ADATBÁZIS-KEZELÉS. A MySQL adatbáziskezelő PHP folytatás JDBC, ODBC

Java grafikai lehetőségek

Java servlet technológia 1 / 40

Adatbázis alapú rendszerek gyakorlat Adatbázis alapú alkalmazásfejlesztés Java, C# környezetben

Web-fejlesztés NGM_IN002_1

abkezel.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.sql.*; public class abkezel extends JFrame {

Java Server Pages - JSP. Web Technológiák. Java Server Pages - JSP. JSP lapok életciklusa

Java servlet technológia. Web alkalmazások. Servlet-et használni érdemes, ha. JSP-t használni érdemes, ha. Servlet-JSP kombináció (MVC) szükséges, ha

Az osztályok csomagokba vannak rendezve, minden csomag tetszőleges. Könyvtárhierarhiát fed: Pl.: java/util/scanner.java


Java szervlet technológia

A WEB programozása - JavaScript 6 dr.gál Tibor őszi előadás. A Windows Scripting Host (WSH)

Adabáziselérés ODBC-n keresztül utasításokkal C#-ban

Java programozási nyelv /ősz 9. óra. Java Server Pages. JSP technika alapjai

PHP alapjai, bevezetés. Vincze Dávid Miskolci Egyetem, IIT

Stateless Session Bean

Java bevezet o Kab odi L aszl o Kab odi L aszl o Java bevezet o

Enterprise JavaBeans. Ficsor Lajos Általános Informatikai Tanszék Miskolci Egyetem. Az Enterprise JavaBeans

A JavaServer Pages (JSP)

A WEB programozása - Bevezetés őszi félév Dr. Gál Tibor

és az instanceof operátor

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

A JavaServer Pages (JSP)

OO PDO. Tehát PDO használatával, könnyen átállhatunk egy másik adatbáziskezelőre, anélkül hogy a kódot teljes egészében újraírnánk.

B I T M A N B I v: T M A N

Természetesen készíts egy csempe nevű könyvtárat és ide mentsd az index.html állományt.

A. függelék Webalkalmazások

Kompozit alkalmazások fejlesztése. IBM WebSphere Portal Server

A JavaServer Pages (JSP)

Excel ODBC-ADO API. Tevékenységpontok: - DBMS telepítés. - ODBC driver telepítése. - DSN létrehozatala. -Excel-ben ADO bevonása

Java és web programozás

Adatbázis-kezelés ODBC driverrel

Helyes-e az alábbi kódrészlet? int i = 1; i = i * 3 + 1; int j; j = i + 1; Nem. Igen. Hányféleképpen lehet Javaban megjegyzést írni?

JAVA PROGRAMOZÁS 8.ELŐADÁS

Enterprise JavaBeans 1.4 platform (EJB 2.0)

Java és web programozás

Szálkezelés. Melyik az a hívás, amelynek megtörténtekor már biztosak lehetünk a deadlock kialakulásában?

Oracle Containers for Java - j2ee alkalmazás szerver funkciók. Molnár Balázs Oracle Hungary

Java Database Connectivity (JDBC)

SQL*Plus. Felhasználók: SYS: rendszergazda SCOTT: demonstrációs adatbázis, táblái: EMP (dolgozó), DEPT (osztály) "közönséges" felhasználók

MVC Java EE Java EE Kliensek JavaBeanek Java EE komponensek Web-alkalmazások Fejlesztői környezet. Java Web technológiák

Kivételek kezelése (exception handling) Hibakezelés old style. Kivételkezelés

Java és web programozás

SZÁMÍTÓGÉPES ADATBÁZIS-KEZELÉS. A MySQL adatbáziskezelő A PHP programozási nyelv JDBC, ODBC

Struts2 keretrendszer

Az új be- és kimenet könyvtár

COSC 2206 Internet Tools. Java Servlets

Java Programozás 11. Ea: MVC modell

Adatbázis Rendszerek II. 1. SQL programozási felületek 39/1B IT MAN

Szoftvertechnológia alapjai Java előadások

Biztonság java web alkalmazásokban

Memória játék. Felhasználói dokumentáció

MySQL kontra MongoDB programozás. SQL és NoSQL megközelítés egy konkrét példán keresztül

ANDROID ALKALMAZÁSFEJLESZTÉS

JDBC - adatbáziskezelés

Programozási nyelvek Java

Java Programozás 4. Gy: Java GUI. Tipper, MVC kalkulátor

Java programozási nyelv

OOP: Java 8.Gy: Abstract osztályok, interfészek

Programozás és adatbázis kezelés PHP ben

Segédanyag: Java alkalmazások gyakorlat

ASP és Java Servlet technológia összehasonlítása

Grafikus keretrendszer komponensalapú webalkalmazások fejlesztéséhez

OBJEKTUM ORIENTÁLT PROGRAMOZÁS JAVA NYELVEN. vizsgatételek

Kilencedik témakör: Lazarus-Firebird. Készítette: Dr. Kotsis Domokos

Model View Controller alapú alkalmazásfejlesztés

Java Programozás 6. Gy: Java alapok. Adatkezelő 2.rész

A gyakorlat során az alábbi ábrán látható négy entitáshoz kapcsolódó adatbevitelt fogjuk megoldani.

Web programozás. 3. előadás

Webfejlesztés alapjai

Web-fejlesztés NGM_IN002_1

PHP. Telepítése: Indítás/újraindítás/leállítás: Beállítások: A PHP nyelv

Kivételkezelés, beágyazott osztályok. Nyolcadik gyakorlat

AWK programozás, minták, vezérlési szerkezetek

WEBFEJLESZTÉS 2. MUNKAMENET-KEZELÉS, HITELESÍTÉS

Multimédia 2017/2018 II.

OOP #14 (referencia-elv)

Java Servletek alapjai

Objektum Orientált Programozás. 11. Kivételkezelés 44/1B IT MAN

JAVA SE/ME tanfolyam tematika

Abstract osztályok és interface-ek. 7-dik gyakorlat

Java programozási nyelv 10. rész Input/output kezelés

Segédanyag: Java alkalmazások gyakorlat

Kliens oldali SQL-API

Webes alkalmazások fejlesztése 4. előadás. Megjelenítés és tartalomkezelés (ASP.NET)

Tartalom DCOM. Történeti áttekintés. Történeti áttekintés. Történeti áttekintés. Történeti áttekintés

Átírás:

SZERVLETEK Általános jellemzők A WEB kiszolgálók funkcionalitását bővítik Appletek az ügyfél oldali szervletek a kiszolgáló oldali Java alkalmazások A CGI programok alternatívái De nem külön processzként, hanem csak külön szálként futnak sokkal hatékonyabbak Java nyelv miatt hordozhatók (portabilitás) Egy ún. szervlet konténerben futnak, ami sok feladatot megold helyettük (kódolás-dekódolás, hitelesítés, titkosítás, stb.) Architektúra Protokoll-független (általános) szervletek a java.servlet.genericservlet osztályt bővítik HTTP szervletek a java.servlet.httpservlet osztályt bővítik Tipikusan csak a doget() és a dopost() metódusokat definiáljuk felül, bár a doput() és a dodelet() felüldefiniálása is néha szükséges A dohead(),dotrace() és dooptions() alapértelmezett implementációi szinte mindig megfelelőek 1

Életciklus Szervlet betöltése Adminisztrátori parancsra Felhasználó felöli kérelemre Egy-egy felhasználói kérelemre, egy-egy újabb szálon indul el a szervlet végrehajtása (közös erőforrásokhoz való hozzáférést szinkronizálni kell!) Ha nincs kiszolgálandó kérelem, akkor is a memóriában marad a szervlet A kiszolgáló csak akkor távolítja el a memóriából, ha Régóta nem használták és hely kell új betöltendő szervleteknek De újabb ügyfél kérelemre ismét betölti A szervlet betöltésekor meghívódik az init() metódusa Az inicializálás végrehajtása után az ügyfél kérelmeket a process() metódusban fogadja Minden ügyfél kérelemre egy új szálban a service() metódust hajtja végre. Ez fogadja az ügyfél kérelmeket és küldi el a válaszokat Több szál egyidejű végrehajtása miatt: szálbiztosan kell implementálni a service() metódust SingleThreadMode interfész implementálása: csak egyetlen szál futhat De több szervlet működhet, külső erőforrások szinkronizálása továbbra is szükséges - csak a példányváltozókat nem kell szinkronizálni A szervletek fejlesztése Két szükséges dolog: Servlet API a fordításhoz Szervlet futtatására alkalmas webkiszolgáló Legjobb ingyenes szervlet- és JSP-képes webkiszolgáló a Jakarta Tomcat Letölthető: http://jakarta.apache.org/tomcat címről Fordítás A javac fordítónak el kell érni a servlet-api.jar jsp-api.jar (ezeket csak a JSP használatakor) állományokat. Legegyszerűbb megoldás: a fentiek bemásolása a jdkjdk_home/jre/lib/ext könyvtárba a TOMCAT_HOME/common/lib könyvtárából Telepítés A legegyszerűbb esetben, csak.html állományok esetén egy jegyzetek nevű alkalmazás telepítése TOMCAT_HOME/webapps/jegyzetek TOMCAT_HOME/webapps/jegyzetek/WEB-INF/web.xml TOMCAT_HOME/webapps/jegyzetek/html1.html TOMCAT_HOME/webapps/jegyzetek/html2.html... TOMCAT_HOME/webapps/jegyzetek/htmln.html s a web.xml tartalma <?xml version="1.0" encoding="iso-8859-1"?> <web-app> </web-app> A web.xml az ún. deployment descriptor (telepítési leíró) analóg a környezeti változókkal, de xml szintaxissal írja le az alkalmzás telepítéséhez és használatához szükséges információt 2

Ha szervleteket is használni akarunk, akkor járulékos könyvtár és járulékos bejegyzés szükséges a web.xml-ben A járulékos könyvtár a class fájlok elhelyezésére.../webapps/jegyzetek/web-inf/classes/class1.class....../webapps/jegyzetek/web-inf/classes/classn.class A járulékos bejegyzés a web.xml fájlban <servlet> <servlet-name>s1</servlet-name> <servlet-class>class1</servlet-class> </servlet>... <servlet> <servlet-name>sn</servlet-name> <servlet-class>classn</servlet-class> </servlet> <servlet-mapping> <servlet-name>s1</servlet-name> <url-pattern>/sv/serv1</url-pattern> </servlet-mapping>... <servlet-mapping> <servlet-name>sn</servlet-name> <url-pattern>/servn</url-pattern> </servlet-mapping> Hozzáférés aclass1.class szervlethez http://localhost:8080/jegyzetek/sv/serv1 http://localhost:8080/jegyzetek/servn Megjegyzések A web.xml-ben a elemek sorrendje kötött! Az url-pattern elemben megadott elérési út az alkalmazás gyökerétől értendő, s az előző példában szereplősv mappa használata természetesen nem kötelező A class fájlok viszont mindig a classes könyvtárban, ill. annak a package struktúrát tükröző alkönyvtáraiban helyezendők el. Ha pl. a classi.class fájlban a package myclasses; szerepelt, akkor annak elhelyezése.../classes/myclasses/classi.class s a web.xml fájlban a <servlet-class> bejegyzés az alábbiak szerinti <servlet-class>myclasses.classi</servlet-class> A web.xml sok egyéb fontos információt tartalmazhat. Például egy adatbázis name/psw értékét nem célszerű beépíteni magába a szervletbe, sokkal jobb, ha azt a telepítési leíróból olvassuk be. Ennek megfelelően egy módosított <servlet> elem, s a paraméterek beolvasása <servlet> <servlet-name>servleta</servlet-name> <servlet-class>exampleservlet</servlet-class> <init-param> <param-name>dbuser</param-name> <param-value>annus</param-value> </init-param> <init-param> <param-name>dbpsw</param-name> <param-value>vizonto</param-value> </init-param> </servlet> //S a beolvasásuk a szervletben String username = getinitparameter("dbuser"); String userpsw = getinitparameter("dbpsw"); Tipikus feladatokat ellátó szervletek Ügyféltől független HTML oldal generálása http://localhost:8080/eloadasservlet/elsoszervletem public class ElsoSzervletem extends HttpServlet { public void doget(httpservletrequest req, HttpServletResponse res) // A válasz tartalom-típusának (MIME) beállítása res.setcontenttype("text/html"); // A HttpServletResponse osztály getwriter() metódusával egy // PrintWriter karakter csatorna létrehozása a ügyfél felé PrintWriter out = res.getwriter(); // A HTML oldal tartalmának elküldése az ügyfélhez a // létrehozott karakter csatornán keresztül "<HTML>"); "<HEAD><TITLE>Elso szervletem</title></head>"); "<BODY><BIG>Hello World</BIG></BODY></HTML>"); 3

Ügyféladattól függő HTML oldal generálása http://localhost:8080/eloadasservlet/hello.html // Ürlapot tartalmazó weboldal, az elküldött adat alapján // kell generálni a HTML oldalt <HTML> <HEAD> <TITLE>Bemutatkozás</TITLE> </HEAD> <BODY> <FORM METHOD=GET ACTION="Hello"> <!-- <FORM METHOD=GET ACTION="/eloadasServlet/Hello"> --> Ha nem sértem meg, megkérdezhetném a nevét? <INPUT TYPE=TEXT NAME="KliensNeve"> <INPUT TYPE=SUBMIT VALUE="Elküldés"> </FORM> </BODY> </HTML> public class Hello extends HttpServlet { public void doget (HttpServletRequest req, HttpServletResponse res) res.setcontenttype("text/html"); PrintWriter out = res.getwriter(); String nev = req.getparameter("kliensneve"); "<HTML><HEAD><TITLE>Üdvözölés</TITLE></HEAD>"); "<BODY>"); "Üdvözöllek " + nev + "!"); "</BODY></HTML>"); public String getservletinfo() { return "Szervlet, amely üdvözli azt az ügyfelet, aki hívta"; public void dopost(httpservletrequest req, HttpServletResponse res) doget(req,res); Fájlok használata értékelő rendszer http://localhost:8080/eloadasservlet/ertekeles.html <html> <head> <META http-equiv="content-type" content="text/html; charset=iso-8859-2"> <script> function check_and_send() { var re = /^\s*[1-5]\s*$/; if(document.f.t1.value.match(re) == null) { alert('az első mező értéke nem 1-5 között van'); return; if(document.f.t2.value.match(re) == null) { alert('a második mező értéke nem 1-5 között van'); return; if(document.f.t3.value.match(re) == null) { alert('a harmadik mező értéke nem 1-5 között van'); return; document.f.submit(); </script> </head> <body> <center> <h2 style="background-color:red; color:white; font-weight:bold; width:300px"> Osztályozza az előadót!</h2> <p> <form name=f method=post action="/eloadasservlet/ertekeles"> <table> <tr><td>az előadó felkészültsége (1-tol 5-ig)</td> <td><input type=text name=t1 size=1></td></tr> <tr><td>az előadó tárgyi tudása (1-tol 5-ig)</td> <td><input type=text name=t2 size=1></td></tr> <tr><td>az előadás érthetosége (1-tol 5-ig)</td> <td><input type=text name=t3 size=1></td></tr> <tr colspan=2><td align=center> <input type=button value=elküldés size=30 onclick="check_and_send()"> <!--<input type=submit value=elküldés size=30 onclick="check_and_send(); return false;"> --> <input type=reset value=törlés></td></tr> </table> </form> </body> </html> 4

import java.util.*; public class ertekeles extends HttpServlet { public void dopost(httpservletrequest req, HttpServletResponse res) PrintWriter out = null; // Az urlapból elküldött adatok beolvasása a req // objektumból. // A t1 nevu szövegmezo értékének eloállítása String [] t1 = req.getparametervalues("t1"); // A t2 nevu szövegmezo értékének eloállítása String [] t2 = req.getparametervalues("t2"); // A t3 nevu szövegmezo értékének eloállítása String [] t3 = req.getparametervalues("t3"); // A beolvasott adatok beírás egy fájlba hozzáfuzéssel // sorvéggel ellátva // Egy ertekeles.txt nevu fájl megnyitása hozzáfuzésre String realfilepath = getservletcontext().getrealpath("data/ertekeles.txt"); FileOutputStream fos = new FileOutputStream(realFilePath, true); // t1, t2, t3 értékének hozzáfűzése fos.write((byte)(t1[0].charat(0))); fos.write((byte)(t2[0].charat(0))); fos.write((byte)(t3[0].charat(0))); // Újsor karakter hozzáfűzése, s a fájl lezárása fos.write((byte)'\n'); fos.close(); // a válsz fejléc tartalomtípus (content-type) beállítása res.setcontenttype("text/html"); // Referencia a válasz PrintWriter objektumára out = res.getwriter(); // HTML oldal generálása az ügyfél felé "<HTML><HEAD><TITLE>FormServlet output</title></head>"); "<BODY BGCOLOR=#FFFFFF><P>"); "<center><h2>köszönjük az értékelését.</h2></center>"); "Ha kiváncsi az eddigi értékelés átlagára, "); "akkor<a" + "href=\"http://localhost:8080/eloadasservlet/ertekeles1\"> + " kattintson ide.</a>"); "</BODY></HTML>"); // A writer lezárása; a válasz elküldve. out.flush(); out.close(); import java.util.*; public class ertekeles1 extends HttpServlet { public void doget(httpservletrequest req, HttpServletResponse res) throws ServletException { PrintWriter out = null; try { // A válasz fejléc tartalomtípus (content-type) beállítása res.setcontenttype("text/html"); // Referencia a PrintWriter objektumra out = res.getwriter(); // HTML oldal generálása és elküldése az ügyfélhez "<HTML><HEAD><meta http-equiv=\"content-type\"" + "content=\"text/html; charset=iso-8859-2\">"); "<TITLE>FormServlet output</title></head>"); "<BODY BGCOLOR=#FFFFFF><P>"); "<center><h2 style=\"background-color:red; " + "color:white; font-weight:bold; width:300px\">" + "Az értékelés átlagolt eredménye</h2>"); // Adatok olvasása az ertekeles.txt fájlból, az átlagok szám. int x1=0; int x2=0; int x3=0; int n =0; try { String realfilepath = getservletcontext().getrealpath("data/ertekeles.txt"); FileReader fr = new FileReader(realFilepath); BufferedReader br = new BufferedReader(fr); String s; while((s=br.readline())!=null) { n++; int x = Integer.valueOf(s).intValue(); x1 += x/100; x2 += (x-(x/100)*100)/10; x3 += (x%100)%10; fr.close(); catch (IOException e) {e); "<table bgcolor=black>"); "<tr><td><font color=white><b>az előadó " + "felkészültésge</font></td><td>" + "<font color=yellow><b>" + (float)x1/n +"</td></tr>"); "<tr><td><font color=white><b>az előadó tárgyi " + "tudása</font></td><td><font color=yellow><b>" + (float)x2/n +"</td></tr>"); 5

"<tr><td><font color=white><b>az előadás " + "érthetosége</font></td><td><font color=yellow><b>" + (float)x1/n +"</td></tr>"); "<tr><td><font color=white>" + <b>a szavazatok " + "száma</font></td><td>" + <font color=yellow><b>" + n +"</td></tr></table></center>"); catch(exception e) { e.printstacktrace(); e); "</BODY></HTML>"); // A Writer lezárása, a válasz elküldve. out.flush(); out.close(); Adatbázisok használata Egyetlen eltérés a közönséges Java alkalmazásokhoz: hol kell elhelyezeni az adott adatbázis meghajtó programjait? Közönséges Java alkalmazás A meghajtó programok a classpath-ban, vagy Pl. az Oracle esetén a clases12.zip-et az alkalmazással azonos könyvtárba téve: Java cp.;classes12.zip DBKezeloProgram Szervlet esetén Nem archiv fájlok (.class) esetén a class fájlok helye../alkalmazas/web-inf/classes/ Archiv fájlok (.jar vagy.zip) esetén../alklamazas/web-inf/lib/ Vagy Tomcat_Home/common/lib/ ODBC esetén a szükséges sun.jdbc.odbc.jdbcodbcdriver a szabvány könyvtárból elérhető Példa: táblázat letöltése a böngészőbe http://localhost:8080/eloadasservlet/dbservlet0 Adott adatbázisból adott táblázat rekordjainak olvasása és HTML táblázat formájú megjelenítése az ügyfél böngészőjében Hozzáférés ODBC DSN-t használva Görgethető kialakítású táblázat megjelenítés Táblázat fejléce és tartalma két külön táblázatban A tartalom táblázatot DIV elemben elhelyezve, a görgethetőséget az overflow=auto jellemzővel állítjuk be Ha a táblázat mérete meghaladja a specifikált méretet, akkor automatikusan görgethető rétegű megjelenítésbe vált át a rendszer import java.sql.*; public class DBServlet0 extends HttpServlet { public void doget(httpservletrequest req, HttpServletResponse resp) Példa: táblázat letöltése a böngészőbe (1. folytatás) // Adatbázis meghajtó ODBC esetén String driver = "sun.jdbc.odbc.jdbcodbcdriver"; // Adatbázis meghajtók Oracle, Sybase és mysql esetén // String driver = "oracle.jdbc.driver.oracledriver"; // String driver = "com.sybase.jdbc.sybdriver"; // String driver = "com.mysql.jdbc.driver"; // Adatbázis URL ODBC DNS esetén String url = "jdbc:odbc:tanszek"; // Adatbázis URL Oracle esetén // String url = "jdbc:oracle:thin:@host:port:dbname"; // Adatbázis URL Sybase esetén // String url = // "jdbc:sybase:tds:@host:port:?servicename=dbname"; // Adatbázis URL mysql esetén // String url = "jdbc:mysql://host/dbname"; // Az adatbázishoz elküldendo sql utasítás String query = "SELECT * FROM munkatarsak ORDER BY Név"; 6

Példa: táblázat letöltése a böngészőbe (2. folytatás) try { // Az adatbázis meghajtó betöltése Class.forName(driver); // A kapcsolat létrehozása az adatbázissal // DriverManager.getConnection(url,"db_login","db_jelszo" ); Connection con = DriverManager.getConnection(url,"",""); // Az utasításobjektum létrehozása Statement stmt = con.createstatement(); // Az sql utasítás végrehajtása, a visszakapott érték // egy eredménykészlet (absztrakt táblázat) ResultSet rs = stmt.executequery(query); // Az eredmény megjelenítése az ügyfél böngészojében printresultset(resp,rs); // Az eredménykészlet-, utasítás- és kapcsolati obj. lezárása rs.close(); stmt.close(); con.close(); // end try Példa: táblázat letöltése a böngészőbe (3. folytatás) catch (SQLException ex) { // Az adatbázissal való kapcsolat során fellépő hiba // elküldése az ügyfél böngészőjébe // PrintWriter kimeneti csatorna megnyitása az ügyfél felé PrintWriter out = resp.getwriter(); // Tartalomtípus (MIME típus) beállítása a válasz fejlécben resp.setcontenttype("text/html"); while (ex!= null) { // A fellépett hibák leírásának elküldése out.println ("SQL Exception: " + ex.getmessage()); ex = ex.getnextexception(); // end while // end catch SQLException catch (java.lang.exception ex) { PrintWriter out = resp.getwriter(); resp.setcontenttype("text/html"); // Egyéb, nem az adatbázis kommunikációs hiba elküldése // az ügyfél böngészőjébe out.println ("Exception: " + ex.getmessage ()); // end doget Példa: táblázat letöltése a böngészőbe (4. folytatás) // Az eredmények megjelenítése az ügyfél böngészojében private void printresultset(httpservletresponse resp, ResultSet rs)throws SQLException { try { // PrintWriter típusú kimeneti csatorna megnyitása PrintWriter out = resp.getwriter(); // A weboldalt statikus elemeinek generálása az ügyfél // böngészőjében "<html>"); "<head><title>dbservlet</title>"); "<style type=text/css>"); "td {width:200;font-size:14pt;font-family:helvetica"); "</style></head>"); "<body>"); "<table border=1 style='width:600;" + "background-color:black'>"); "<caption><h2>munkatársak adatai</h2></caption>"); "<tr style='color:white; font-weight:bold;'>"); Példa: táblázat letöltése a böngészőbe (5. folytatás) // A metaadatokat tartalmazó objektum létrehozása a // visszakapott táblázat oszlopneveinek és az oszlopok // számának megállapítására ResultSetMetaData rsmd = rs.getmetadata(); // Az oszlopok számának meghatározása int numcols = rsmd.getcolumncount (); // Az oszlopok neveinek generálása az első táblázatban for(int i=1; i<=numcols; i++) out.print("<td>" + rsmd.getcolumnname(i) + "</td>" ); "</tr>"); "</table>"); // A div elem létrehozása fix mérettel és overflow=auto // tulajdonsággal "<div style='overflow:auto; width:616;" + "height: 160px;'>"); 7

Példa: táblázat letöltése a böngészőbe (6. folytatás) // A második táblázat létrehozása "<table border=1 style='background-color:#c0c0c0'>"); // A táblázat sorainak generálása az adatbázisból // visszakapott eredménykészlet alapján while ( rs.next() ) { "<tr>"); for (int i=1; i<=numcols; i++) { out.print("<td>" + rs.getstring(i) + "</td>" ); // end for "</tr>"); // end while "</table>"); "</div>"); "</body>"); "</html>"); out.close(); // end try catch ( IOException except) { // end catch // end printresultset // end DBServlet0 Példa: Kétirányú kommunikáció az adatbázissal és az ügyféllel http://localhost:8080/eloadasservlet/dbservlet1 A letöltött táblázat alatt jelenítsünk meg egy újabb táblázatot Annak egy sora három szövegmezőt tartalmazzon Az ide beírt új rekord kerüljön el az adatbázisba Azonos Nev mező esetén csak módosuljon a rekord A kiolvasott táblázat megjelentetéséig a megoldás azonos az előbbivel, ezért csak a hátralévő rész: Import java.io.*; //... //... // Űrlap generálása az ügyfél böngészőjében "<form metdod='get' action='/eloadasservlet/dbservlet2'>"); Példa: Kétirányú kommunikáció az adatbázissal és az ügyféllel (folyt.) // Az űrlapon belül egy táblázat generálása "<table border=1 style='width:600;'>"); // A tábázat egy sorában numcols darab szövegmező elem gene- // rálása, a name tulajdonságnak cella1,... neveket adva "<tr>"); for (int i=1; i<=numcols; i++) { out.print("<td><input type=text value='' name=cella" + i + " style='width:100%'></td>"); // end for "</tr>"); // numcols oszlopot átfogó Submit nyomógomb generálása out.print("<tr><td colspan="+ numcols + " style='width:100%'>" + "<input type='submit' style='width:100%'></td>"); "</tr>"); "</table>"); "</form>"); "</body>"); "</html>"); out.close(); // end try catch ( IOException except) { // end catch // end printresultset // end DBServlet1 Példa: Kétirányú komm. (DBServlet2) import java.sql.*; public class DBServlet2 extends HttpServlet { public void doget(httpservletrequest req, HttpServletResponse resp) String driver = "sun.jdbc.odbc.jdbcodbcdriver"; String url = "jdbc:odbc:tanszek"; try { Class.forName(driver); Connection con = DriverManager.getConnection(url,"",""); Statement stmt = con.createstatement(); // A táblázat beolvasása annak eldöntésére, hogy // insert vagy update sql utasítást kell-e végrehajtani String query = "SELECT * FROM munkatarsak"; ResultSet rs = stmt.executequery(query); 8

Példa: Kétirányú komm. (DBServlet2) (1. folytatás) ResultSetMetaData rsmd = rs.getmetadata(); int numcols = rsmd.getcolumncount (); boolean newrecord=true; String Név = req.getparameter("cella1"); String Beosztás = req.getparameter("cella2"); String Életkor = req.getparameter("cella3"); while ( rs.next() ) { if(rs.getstring(1).equals(név)){ newrecord=false; break; rs.close(); stmt.close(); stmt = con.createstatement(); String sql=null; if(newrecord){ // A megadott nevu személy nem szerepel az // adatbázisban, így insert utasítást kell végrehajtani sql = "insert into munkatarsak (Név,Beosztás,Életkor)" + " values('"+név+"','"+beosztás+"','"+életkor+"')"; else{ Példa: Kétirányú komm. (DBServlet2) (2. folytatás) // A megadott nevu személy szerepel az // adatbázisban, így update utasítást kell végrehajtani sql = "update munkatarsak set Beosztás='" + Beosztás + "', Életkor='" + Életkor + "' where Név='" + Név +"'"; stmt.executeupdate(sql); stmt.close(); con.close(); // end try catch (SQLException ex) { PrintWriter out = resp.getwriter(); resp.setcontenttype("text/html"); while (ex!= null) { out.println ("SQL Exception: " + ex.getmessage ()); ex = ex.getnextexception (); // end while // end catch SQLException catch (java.lang.exception ex) { PrintWriter out = resp.getwriter(); resp.setcontenttype("text/html"); out.println ("Exception: " + ex.getmessage ()); Példa: Kétirányú komm. (DBServlet2) (3. folytatás) // Az adatbázis műveletek végrehajtása befejeződött, // a végrehajtás átirányítása a DBServlet1 szervletre // (a magyarázatot lásd a fejezet végén) RequestDispatcher dispatcher = getservletcontext().getrequestdispatcher("/dbservlet1"); dispatcher.forward(req,resp); // end doget // end DBServlet2 Munkafolyamatok (session) kezelése Bizonyos idő alatt azonos felhasználótól érkező kérelmek Oldalak között navigáló felhasználó bizonyos adataira szükség lehet az elhagyott weboldalak kontextusából (online áruház: kosár tartalmának megtartása az oldalak közötti navigálás alatt) HTTP állapotmentes, ezért nem lehet a protokollra támaszkodva megoldani. Három megoldás: Sütik URL átírás Rejtett mezők használata Sütik: az ügyfél gépén tárolható információ. Felhasználható a munkafolyamat állapotváltozóinak tárolására. De nem mindig jó, mert ki lehet kapcsolni a sütiket. URL átírás: minden ugrást kiváltható URL-hez hozzácsatolunk valamilyen adatot, pl.: http://host/path/file.html;sessionid=123456 tetemes munkával járhat (dinamikus URL, pl.location.href is kiegészítendő, de mindig használható) Rejtett mező elhelyezése, amelynek tartalma is elküldődik: <input type="hidden" name="session" value="123456"> 9

A szervletek hatékonyan támogatják a munkafolyamatok kezelését HttpSession objektum: a munkafolyamat valamennyi szervletje számára hozzáférhető adatokat tárolja. Referencia a session objektumra HttpSession session = request.getsessin(true); A true argumentum miatt automatikusan létrehozza, ha nem létezett. Hozzáférés a session objektumhoz: public void setattribute(string kulcsnev, Object value) public Object getattribute(string kulcsnev) Néhány további metódus public void removeattribute(string kulcsnev) public Strin[] getattributenames() public String getid() public Boolean isnew() public long getcreationtime() public long getlastaccessedtime() public int getmaxinactiveintervall() public void setmaxinactiveinterval(int seconds) public void invalidate() Az ügyfélnek elküldendő URL-ek kódolása a HttpServletResponse objektum encodeurl metódusával. Például: String eredetiurl = valamirelativvagyabszoluturl; String kodolturl = response.encodeurl(eredetiurl); "<a href=\"" + kodolturl + "\>...</a>"); Példa egy munkafoyamatra Belépés a munkafolyamatba: http://localhost:8080/eloadasservlet/munkafolyamat.html Itt a felhasználó megadja a nevét, s a Submit hatására áttér az s1 szevletre <h2>munkafolyamat tesztelése</h2> <p>adja meg egy nevet. Az s1 szervlet ezt egy munkafolyamat-váltzóban tárolja, s ezután a munkafolyamat többi szervletei, az s2, s3 és s4 is hozzá tudnak majd ehhez férni. </p> <form method=get action="/eloadasservlet/s1"> Adja meg a nevét: <input type=text name=nnn> <input type=submit> </form> Az s1 szervlet import java.util.*; public class s1 extends HttpServlet { public void doget( HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException { HttpSession session; if(request.getsession(false) == null){ session = request.getsession(true); String nev = request.getparameter("nnn"); session.setattribute("felhasznaloneve", nev); Vector v = new Vector(); session.setattribute("kerelmek", v); session = request.getsession(true); Vector kerelmek = (Vector)session.getAttribute("kerelmek"); kerelmek.addelement(request.getrequesturi()); session.setattribute("kerelmek",kerelmek); Az s1 szervlet (1. folytatás) response.setcontenttype("text/html"); PrintWriter out = response.getwriter(); "<html><head><meta http-equiv='content-type'" + " content='type=text/html;charset=iso-8859-2'></head>" + "<body>" + "<h2>üdvözlöm kedves</h2>" + (String)session.getAttribute("felhasznaloNeve") + "<br>a munkafolyamat elso lapján" + "<p>" + "Az Ön által eddig meglátogatott oldalak<br>"); for(int i=0; i<kerelmek.size(); i++){ (String)kerelmek.elementAt(i) + "<br>"); String s2encoded = response.encodeurl("/eloadasservlet/s2"); String s3encoded = response.encodeurl("/eloadasservlet/s3"); String s4encoded = response.encodeurl("/eloadasservlet/s4"); 10

Az s1 szervlet (2. folytatás) "<p>ha az alábbi linkek egyikére kattint, akkor eljuthat" + "a munkafolyamat egy másik lapjára" + "<br><a href='" + s2encoded + "'>" + + "Munkafolyamat 2. lapjára</a>" + "<br><a href='" + s3encoded + "'>" + "Munkafolyamat 3. lapjára</a>" + + "<br><a href='" + s4encoded + "'>" + "Munkafolyamat 4. lapjára</a>" + "<p>ennek a munkafolyamatnak a kiszolgáló a következo" + " sessionid értéket adta:<br> sessionid= " + session.getid() + "</body></html>"); public void dopost(httpservletrequest req, HttpServletResponse res) doget(req,res); A többi szervlet Eltérés az s1-től: - Nem kell vizsgálni, hogy a munkafolyamat létre van-e hozva - Nem kell a munkafolyamatba beírni a nevet - A linkek között a saját URL-jük helyett az s1 URL-jét szerepeltetik Például s2 import java.util.*; public class s2 extends HttpServlet { public void doget(httpservletrequest request, HttpServletResponse response) throws ServletException,IOException { HttpSession session = request.getsession(true); Vector kerelmek = (Vector)session.getAttribute("kerelmek"); kerelmek.addelement(request.getrequesturi()); session.setattribute("kerelmek",kerelmek); s2 (1.folytatás) s2 (2.folytatás) response.setcontenttype("text/html"); PrintWriter out = response.getwriter(); "<html><head><meta http-equiv='content-type'" + " content='type=text/html;charset=iso-8859-2'></head>" + "<body>" + "<h2>üdvözlöm kedves</h2>" + (String)session.getAttribute("felhasznaloNeve") + "<br>a munkafolyamat második lapján" + "<p>" + "Az Ön által eddig meglátogatott oldalak<br>"); for(int i=0; i<kerelmek.size(); i++){ (String)kerelmek.elementAt(i) + "<br>"); String s1encoded = response.encodeurl("/servlet/s1"); String s3encoded = response.encodeurl("/servlet/s3"); String s4encoded = response.encodeurl("/servlet/s4"); "<p>ha az alábbi likek egyikére kattint, akkor eljuthat" + "a munkafolyamat egy másik lapjára" + "<br><a href='" + s1encoded + "'>Munkafolyamat 1. lapjára</a>" + "<br><a href='" + s3encoded + "'>Munkafolyamat 3. lapjára</a>" + "<br><a href='" + s4encoded + "'>Munkafolyamat 4. lapjára</a>" + "<p>ennek a munkafolyamatnak a kiszolgáló a következo" + " sessionid értéket adta:<br> sessionid= " + session.getid() + "</body></html>"); public void dopost(httpservletrequest req, HttpServletResponse res) doget(req,res); Másik példa http://localhost:8080/eloadasservlet/jatek 11

Egyéb tipikus feladatok HTTP fejlécek Az ügyfél felől érkező HTTP protokoll fejléc olvasása request.getheader("fejlecneve"); // például reguest.getheader("host"); // vagy reguest.getheader("host"); // a fejléc neve nem érzékeny a kis/nagybetűre Több fejlécnévre direkt metódus is használható public String getmethod() public String getprotocol() public int getcontentlength() public String getcontenttype() public Cookie[] getcookies() public Enumeration getheadernames() public Enumeration getheaders() Az első fejléc elemei (method, requesturi, protocol) csak direkt metódussal olvashatók (getmethod(), getrequesturi(), getprotocol())! Példa: Három fejléc beolvasása és megjelenítése a böngészőben táblázatos formában http://localhost:8080/eloadasservlet/reqheaders public class ReqHeaders extends HttpServlet { public void doget (HttpServletRequest request, HttpServletResponse response) response.setcontenttype("text/html"); PrintWriter out = response.getwriter(); "<html><h2>a kérelem fejlécek megjelnítése " + "egy weboldalon</h2>"); "Kérelem parancs: " + request.getmethod() + "<br>" + "Kérelem URI: " + request.getrequesturi() + "<br>" + "Kérelem protokoll: " + request.getprotocol() + "<p>"); "<table border=1>" + "<tr><th>fejléc neve</th><th>fejléc értéke</th></tr>"); Enumeration headernames = request.getheadernames(); while(headernames.hasmoreelements()) { String headername = (String)headerNames.nextElement(); "<tr><td>" + headername + "</td>"); "<td>"+request.getheader(headername)+"</td></tr>"); "</table></html>"); out.close(); Válasz fejlécek A webkiszolgáló tipikus válasza kötött sorrendben az alábbiakból áll - státuszsor - fejlécek - üres sor - tartalom például HTTP/1.0 200 OK Content-Type: text/html <html> Hello Uraim! </html> Akár a státuszkódot, akár a fejléceket is generálhatjuk a szervlettel, de feltétlenül a tartalom generálása előtt! A státusz beállítása public void setstatus(int statuskod) Fejlécek beállítása public void setheader(string fejlecnev, String fejlecertek) Fájlból betölthető kép elküldése az ügyfél böngészőjébe: http://localhost:8080/eloadasservlet/sendimage - a szervlet a háttértárból olvassa be a képet, - meghatározza annak típusát, - ez alapján beállítja a fejlécet, - s végül elküldi a képet import java.util.*; public class sendimage extends HttpServlet { public void doget(httpservletrequest request, HttpServletResponse responsw) throws IOException { // A kép abszolút elérési útjának meghatározása ServletContext sc = getservletcontext(); String filename = sc.getrealpath( "WEB-INF/classes/kep1.jpg"); 12

Fájlból betölthető kép elküldése az ügyfél böngészőjébe (folytatás) // A kép MIME típusának meghatátozása String mimetype = sc.getmimetype(filename); if (mimetype == null) { sc.log("a "+filename + " MIME típusát nem lehetett meghatározni"); response.setstatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; // A tartalomtípus beállítása response.setcontenttype(mimetype); // A méret beállítása File file = new File(filename); response.setcontentlength((int)file.length()); // A fájl és a kimeneti csatorna megnyitása FileInputStream in = new FileInputStream(file); OutputStream out = response.getoutputstream(); // A fájl átmásolása a kimeneti csatornára byte[] buf = new byte[1024]; int count = 0; while ((count = in.read(buf)) >= 0){out.write(buf, 0, count); in.close(); out.close(); Kép generálása és elküldése az ügyfél böngészőjébe: http://localhost:8080/eloadasservlet/imageservlet import java.awt.*; import java.awt.image.*; import com.sun.image.codec.jpeg.*; public class ImageServlet extends HttpServlet { public void doget(httpservletrequest request, HttpServletResponse response) response.setcontenttype("image/jpeg"); // Kép létrehozása int width = 200; int height = 200; BufferedImage image = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB); // Grafikus kontextus elkérése Graphics2D g = (Graphics2D)image.getGraphics(); Kép generálása és elküldése az ügyfél böngészőjébe (folyt.) // Háttér kitöltése g.setcolor(color.yellow); g.fillrect(0, 0, width, height); // Szöveg rajzolása g.setcolor(color.black); g.setfont(new Font("Dialog", Font.BOLD, 20)); g.drawstring("kép generálása",width/2-70,50); // Kör rajzolása g.setcolor(color.black); g.drawoval(width/2-60, 70, 100, 100); // Dispose context g.dispose(); Konkurens hozzáférés megakadályozása //Ez a szervlet egyidejűleg csak egyetlen kérelmet kezel public class MyServlet extends HttpServlet implements SingleThreadModel {... De a szervlet konténer több szervlet példányt is létrehozhat, ezért - bár a szervlet példányváltozóit nem kell szinkronizálni - de a külső erőforrásokat igen! // Kép generálása a válaszba ServletOutputStream sos = response.getoutputstream(); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(sos); encoder.encode(image); 13

Szervletek együttműködése Kommunikáció a futtató környezettel a szervletservletcontext objektumán keresztül public void setattribute(string key, Object obj) public Object getattribute(string key) public Enumeration getattribitenames() public void removeattribute(string key) // A key a tulajdonság minősített neve pl. com.foo.fooservlet.fooservlet // esetén com.foo.fooservlet.fooservlet.kulcs1 // lehet Végleges átirányítás kérelem átirányítása egy másik erőforráshoz (szervlethez, HTML vagy JSP oldalhoz) De ha az kiinduló szervlet már hozzáfért a ServletOutputStream vagy PrintWriter objektumhoz, akkor IllegalStateException lép fel! Tehát csak az egyik - célszerűen - a meghívott írhat a kliens felé. Összetett feladatok esetén célszerű különválasztani az adatfeldolgozó és a weboldal generáló részt. Az előbbit szervlettel, az utóbbit JSP-vel célszerű megoldani. Ennek váza: ServletContext sc = getservletcontext(); RequestDispatcher dispatcher = sc.getrequestdispatcher("/célerőforrás_azonos_kontextusban"); Referencia egy másik szervletservletcontext objektumása public ServletContext getcontext(string localuri) dispatcher.forward(req,res); További példa public void doget(httpservletrequest req, HttpServletResponse res) // Adatfeldolgozást elvégző rész... Átirányítás valamilyen // feltétel szerint kiválasztandó JSP oldalra String operation = reg.getparameter("operation"); if(operation == null) { operation = "ismeretlen"; if(operation.equals("operation1")) { gotopage("/operations/presentation1.jps", req, res); else if(operation.equals("operation2")) { gotopage("/operations/presentation1.jps", req, res); else { gotopage("/operations/unknownrequesthandler.jps", req, res); Ideiglenes átirányítás Ilyenkor a célszervlet tartalma beszúródik a hívás helyén A hívó és a hívott egyaránt küldhet adatokat, de a hívott a fejlécet nem módosíthatja, s ne zárja le a kimeneti csatornát. A RequestDispatcher objektum forward() metódusa helyett az include() metódust kell használni private void gotopage(string address, HttpServletRequest req, HttpServletResponse res) RequestDispatcher dispatcher = getservletcontext().getrequestdispatcher(address); dispatcher.forward(req, res); 14